diff --git a/.gitignore b/.gitignore index 3db1d218759..1e5242e0d57 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,9 @@ Knowage-Python/pythonwebservice/logs/ Knowage-Python/pythonwebservice/cert.pem Knowage-Python/pythonwebservice/key.pem + +Knowage-R/configs.R + +Knowage-R/.Rhistory + +Knowage-R/.RData diff --git a/CLA.md b/CLA.md new file mode 100644 index 00000000000..d7e9f2b8962 --- /dev/null +++ b/CLA.md @@ -0,0 +1,62 @@ +Contributor License Agreement +=============== + +[www.knowage-suite.com](https://www.knowage-suite.com) + +Thank you for your interest in [Knowage Project](https://www.knowage-suite.com). In order to clarify both the intellectual property license, granted with Contributions from any person, and the contribution management guidelines, outlined in order to achieve a project systematic growth, the Knowage Project must have a Contributor License Agreement (or Agreement) that has been accepted by each Contributor, indicating his/her agreement to terms and conditions of this Contributor License Agreement. + +This Agreement is for your protection as a Contributor as well as the protection of ENGINEERING Ingegneria Informatica S.p.A., which keeps the copyright of Knowage software and documentation. This does not change your rights to use your own Contributions for any other purpose. + +This Agreement: + +- clarifies that, to your knowledge, the technology you’ve submitted was developed by you and that you have authority to provide it; +- grants to ENGINEERING Ingegneria Informatica S.p.A. a perpetual, worldwide, no-charge, royalty-free, irrevocable, non-exclusive copyright license to use your Contribution and every derivative work, according to Knowage license. + +**Please read this document carefully before accepting its terms and conditions.** + +Definitions +--------------- + +“Contributor” is the copyright owner that is making this Agreement with ENGINEERING Ingegneria Informatica S.p.A. + +“Engineering” (ENGINEERING Ingegneria Informatica S.p.A.) is the entity owner of the copyright of Knowage software and documentation. + +“Knowage Project” or “Project” shall mean every organization, procedure, mean, practice, term, condition and license, used by ENGINEERING Ingegneria Informatica S.p.A. for the aim of the free/open source Knowage project development by means of all its software components and documentation which are pointed out on the project site: [www.knowage-suite.com](https://www.knowage-suite.com). + +“Contribution” shall mean any original work of authorship, including any modifications or additions to an existing work, which is intentionally submitted by the Contributor to ENGINEERING for inclusion in Knowage software or documentation. For the purpose of this definition, “submitted” means any form of electronic, verbal or written communication sent to ENGINEERING, including but not limited to communication on electronic mailing lists, source code control systems and issue tracking systems that are managed by ENGINEERING for the purpose of discussing and improving Knowage software and documentation, but excluding the communication that is conspicuously marked or otherwise designated in writing by the Contributor as “Not a Contribution”. + +Acceptance and Termination procedure +--------------- + +The Contributor agrees and commits himself/herself to respect both the Contribution Guidelines (you can find it on [www.knowage-suite.com](https://www.knowage-suite.com)) and the Acceptance and Termination procedure, as follows. + +To contribute, the Contributor must accept this Contributor License Agreement and the Contribution Guidelines of this Agreement. Otherwise, ENGINEERING Ingegneria Informatica S.p.A. will not consider his/her Contribution. + +A Developer who has sent Contributions in solid, useful source code and/or documentation and who asked to be a Contributor will be add to our Contributor List published on Knowage website. ENGINEERING will notify to the Contributor via email his/her elevation to Contributor status. + +ENGINEERING can exclude a Contributor from the Contributors list, by its exclusive right, when this Contributor has not respected the above rules repeatedly or when s/he has not contributed for a long period (more than three years). If any of these events occurs, any assignment under this Agreement for the Contributor’s Contribution shall terminate, by a communication that ENGINEERING will send to the Contributor, starting from the date of this communication. + +Contributor’s responsibility +--------------- + +The Contributor owns and has the rights to contribute all source code and related material, intended to be compiled or integrated with the source code for Knowage software and documentation which the Contributor has ever delivered, and the Project has accepted, for incorporation into the technology, made available under the Knowage Project. + +The Contributor grants to comply with the applicable laws and regulations, the Knowage license terms of use and the guiding principles concerning any use of copyrighted materials. + +Copyright assignment by Contributor +--------------- + +Subject to the terms and conditions of this Agreement, the Contributor grants to ENGINEERING Ingegneria Informatica S.p.A. a perpetual, worldwide, no-charge, royalty-free, irrevocable, non-exclusive copyright license to use the Contribution and every derivative work, according to Knowage License. + +The Contributor represents that s/he is legally entitled to grant the above assignment. + +The Contributor represents that his/her Contribution is his/her original creation. + +The Contributor represents that his/her Contribution includes complete details of any third-party license or other restriction of which s/he is personally aware and which are associated with any party of his/her Contribution. + +Miscellaneous Terms +--------------- + +The Agreement is subject to the Italian law and any dispute arising between the Parties relating to this Agreement shall be under the exclusive jurisdiction of the Court of Rome, Italy. + +These Terms constitute the entire agreement between you and ENGINEERING relating to the subject matter herein and supersede all prior communications, agreements, understandings and arrangements between you and ENGINEERING, whether oral or written. diff --git a/Knowage-Python/.dockerignore b/Knowage-Python/.dockerignore new file mode 100644 index 00000000000..f35a3dd2e41 --- /dev/null +++ b/Knowage-Python/.dockerignore @@ -0,0 +1,6 @@ +.git +.idea +__pycache__ +*.pyc +*.pyo +*.pyd \ No newline at end of file diff --git a/Knowage-Python/Dockerfile b/Knowage-Python/Dockerfile new file mode 100644 index 00000000000..7f013a2dd25 --- /dev/null +++ b/Knowage-Python/Dockerfile @@ -0,0 +1,11 @@ +FROM python:3.7 + +COPY . . + +RUN pip install -r requirements.txt + +WORKDIR /pythonwebservice + +EXPOSE 5000 + +CMD [ "python3", "knowage-python.py" ] \ No newline at end of file diff --git a/Knowage-Python/pythonwebservice/__init__.py b/Knowage-Python/pythonwebservice/__init__.py index e69de29bb2d..63f77b6be18 100644 --- a/Knowage-Python/pythonwebservice/__init__.py +++ b/Knowage-Python/pythonwebservice/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python3 + diff --git a/Knowage-Python/pythonwebservice/app/__init__.py b/Knowage-Python/pythonwebservice/app/__init__.py index e69de29bb2d..63f77b6be18 100644 --- a/Knowage-Python/pythonwebservice/app/__init__.py +++ b/Knowage-Python/pythonwebservice/app/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python3 + diff --git a/Knowage-Python/pythonwebservice/app/services/__init__.py b/Knowage-Python/pythonwebservice/app/services/__init__.py index 523a5a4f452..f912cd33bbf 100644 --- a/Knowage-Python/pythonwebservice/app/services/__init__.py +++ b/Knowage-Python/pythonwebservice/app/services/__init__.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + from flask import Flask from flask_cors import CORS diff --git a/Knowage-Python/pythonwebservice/app/services/dataset_service.py b/Knowage-Python/pythonwebservice/app/services/dataset_service.py index 76ceadba77b..89d03b321ec 100644 --- a/Knowage-Python/pythonwebservice/app/services/dataset_service.py +++ b/Knowage-Python/pythonwebservice/app/services/dataset_service.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # diff --git a/Knowage-Python/pythonwebservice/app/services/editmode_service.py b/Knowage-Python/pythonwebservice/app/services/editmode_service.py index 30d5bb80349..609ded90c02 100644 --- a/Knowage-Python/pythonwebservice/app/services/editmode_service.py +++ b/Knowage-Python/pythonwebservice/app/services/editmode_service.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # @@ -45,7 +47,7 @@ def python_html(): python_widget.script = python_widget.script.replace("$P{" + d + "}", "drivers_.get(\'" + d + "\')") #retrieve dataset if python_widget.dataset_name != None: - dataset_file = "tmp/" + python_widget.dataset_name + ".pckl" + dataset_file = constants.TMP_FOLDER + python_widget.dataset_name + ".pckl" df = utils.getDatasetAsDataframe(python_widget) df.to_pickle(dataset_file) python_widget.script = "import pandas as pd\n" + python_widget.dataset_name + " = pd.read_pickle(\"" + dataset_file + "\")\n" + python_widget.script diff --git a/Knowage-Python/pythonwebservice/app/services/viewmode_service.py b/Knowage-Python/pythonwebservice/app/services/viewmode_service.py index 7e6d68ca591..37cdad3c401 100644 --- a/Knowage-Python/pythonwebservice/app/services/viewmode_service.py +++ b/Knowage-Python/pythonwebservice/app/services/viewmode_service.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # diff --git a/Knowage-Python/pythonwebservice/app/utilities/__init__.py b/Knowage-Python/pythonwebservice/app/utilities/__init__.py index e69de29bb2d..63f77b6be18 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/__init__.py +++ b/Knowage-Python/pythonwebservice/app/utilities/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python3 + diff --git a/Knowage-Python/pythonwebservice/app/utilities/constants.py b/Knowage-Python/pythonwebservice/app/utilities/constants.py index ddb9c88e509..77d05dcc48c 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/constants.py +++ b/Knowage-Python/pythonwebservice/app/utilities/constants.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + EDIT_PYTHON_SCRIPTS = "EditPythonScripts" TMP_FOLDER = "app/services/tmp/" LOG_FILE = "logs/knowage-python.log" diff --git a/Knowage-Python/pythonwebservice/app/utilities/cuncurrency_manager.py b/Knowage-Python/pythonwebservice/app/utilities/cuncurrency_manager.py index e8a9c470981..ace1bea9100 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/cuncurrency_manager.py +++ b/Knowage-Python/pythonwebservice/app/utilities/cuncurrency_manager.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + from threading import Lock active_servers = {} #{widget_id : bokeh_server} diff --git a/Knowage-Python/pythonwebservice/app/utilities/objects.py b/Knowage-Python/pythonwebservice/app/utilities/objects.py index ab83b59eba9..0a26f815b0b 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/objects.py +++ b/Knowage-Python/pythonwebservice/app/utilities/objects.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # @@ -63,6 +65,10 @@ def widget_id(self): def script(self): return self._script + @property + def output_variable(self): + return self._output_variable + @script.setter def script(self, value): self._script = value diff --git a/Knowage-Python/pythonwebservice/app/utilities/security.py b/Knowage-Python/pythonwebservice/app/utilities/security.py index c9d5539ac63..8044c860560 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/security.py +++ b/Knowage-Python/pythonwebservice/app/utilities/security.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # diff --git a/Knowage-Python/pythonwebservice/app/utilities/utils.py b/Knowage-Python/pythonwebservice/app/utilities/utils.py index 674a3af9c9f..9fe10edfc87 100644 --- a/Knowage-Python/pythonwebservice/app/utilities/utils.py +++ b/Knowage-Python/pythonwebservice/app/utilities/utils.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + # Knowage, Open Source Business Intelligence suite # Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. # diff --git a/Knowage-Python/pythonwebservice/knowage-python.py b/Knowage-Python/pythonwebservice/knowage-python.py index 2ff3fc30fd8..0273c8671d2 100644 --- a/Knowage-Python/pythonwebservice/knowage-python.py +++ b/Knowage-Python/pythonwebservice/knowage-python.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import sys from app.services import create_app from app.utilities import constants diff --git a/Knowage-Python/requirements.txt b/Knowage-Python/requirements.txt new file mode 100644 index 00000000000..adc7e7eb548 --- /dev/null +++ b/Knowage-Python/requirements.txt @@ -0,0 +1,8 @@ +bokeh==1.3.4 +Flask==1.1.1 +Flask-Cors==3.0.8 +pandas==0.25.1 +pybase64==1.0.1 +PyJWT==1.7.1 +requests==2.22.0 +tornado==6.0.3 \ No newline at end of file diff --git a/Knowage-Python/setup.py b/Knowage-Python/setup.py index 0aea07039b0..353cf5448ad 100644 --- a/Knowage-Python/setup.py +++ b/Knowage-Python/setup.py @@ -1,11 +1,18 @@ +#!/usr/bin/env python3 + import setuptools +def parse_requirements(filename): + """ load requirements from a pip requirements file """ + lineiter = (line.strip() for line in open(filename)) + return [line for line in lineiter if line and not line.startswith("#")] + with open("README.md", "r") as f: long_description = f.read() setuptools.setup( name="knowage-python", - version="0.2.8", + version="1.0", license='AGPL v3', author="Marco Balestri", author_email="marco.balestri@eng.it", @@ -17,16 +24,7 @@ package_data={ '': ['*.html'], }, - install_requires=[ - 'flask', - 'flask_cors', - 'pybase64', - 'bokeh', - 'tornado', - 'requests', - 'pandas', - 'pyjwt', - ], + install_requires = parse_requirements('requirements.txt'), classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: GNU Affero General Public License v3", diff --git a/Knowage-R/configs.R b/Knowage-R/configs.R new file mode 100644 index 00000000000..7b310868bee --- /dev/null +++ b/Knowage-R/configs.R @@ -0,0 +1 @@ +hmac_key <- "abc123" diff --git a/Knowage-R/constants.R b/Knowage-R/constants.R new file mode 100644 index 00000000000..40f5c79d69f --- /dev/null +++ b/Knowage-R/constants.R @@ -0,0 +1,2 @@ +knowage_address <- "0.0.0.0" +r_webservice_port <- 5001 diff --git a/Knowage-R/knowage-r.R b/Knowage-R/knowage-r.R new file mode 100644 index 00000000000..cdff553078e --- /dev/null +++ b/Knowage-R/knowage-r.R @@ -0,0 +1,4 @@ +source("constants.R") + +pr <- plumber::plumb("webservice.R") +pr$run(port = r_webservice_port, host = knowage_address, swagger = FALSE) diff --git a/Knowage-R/utils.R b/Knowage-R/utils.R new file mode 100644 index 00000000000..71ae2b22c96 --- /dev/null +++ b/Knowage-R/utils.R @@ -0,0 +1,69 @@ +library(openssl) +library(jose) +source("configs.R") + +get_libraries <- function(){ + str(allPackages <- installed.packages(.Library, priority = "high")) + lib_matrix <- allPackages[, c(1,3:5)] + lib_info <- lib_matrix[,c(1,2)] + lib_info +} + +resolve_drivers <- function(script, drivers){ + for(name in names(drivers)) { + value <- drivers[[name]] + original <- paste0('\\$P\\{', name , '\\}') + final <- paste0('drivers_[[\\"', name, '\\"]]') + script <- gsub(original,final,script) + } + script +} + +build_parameters <- function(parameters){ + to_return <- list() + if(length(parameters) > 0) { + parameters_df <- as.data.frame(parameters) + for(i in 1:nrow(parameters_df)) { + row <- parameters_df[i,] + name <- row[["name"]] + value <- row[["value"]] + type <- row[["type"]] + if(value == "") { + value <- row[["defaultValue"]] + } + if(type == "Number") { + value <- as.numeric(value) + } + to_return[[name]] <- value + } + } + to_return +} + +resolve_parameters <- function(script, parameters){ + for(name in names(parameters)) { + value <- parameters[[name]] + original <- paste0('\\$P\\{', name , '\\}') + final <- paste0('parameters_[[\\"', name, '\\"]]') + script <- gsub(original,final,script) + } + script +} + +decode_jwt_token <- function(script){ + token <- jwt_decode_hmac(script, secret = hmac_key) + token +} + +get_script_from_token <- function(token){ + script <- token[["script"]] + script +} + +is_dataset_request_authorized <- function(token){ + expirationTime <- token[["exp"]] + now <- as.numeric(as.POSIXct(Sys.time())) + if (now > expirationTime) + FALSE + TRUE +} \ No newline at end of file diff --git a/Knowage-R/webservice.R b/Knowage-R/webservice.R new file mode 100644 index 00000000000..60cc31ce3a8 --- /dev/null +++ b/Knowage-R/webservice.R @@ -0,0 +1,58 @@ +library("jsonlite") +library("base64enc") +source("utils.R") + +#' @post /img +function(dataset, dataset_name=NULL, script, drivers, output_variable){ + env <- new.env() + analytical_drivers <- fromJSON(drivers) + env$drivers_ <- analytical_drivers + script <- resolve_drivers(script, analytical_drivers) + if (!is.null(dataset_name)) { + script <- gsub(dataset_name,"df_",script) + env$df_ <- as.data.frame(fromJSON(dataset)) + } + eval(parse(text=script), envir = env) + enc_img <- base64encode(output_variable) + if (file.exists(output_variable)) + file.remove(output_variable) + enc_img +} + +#' @post /html +function(dataset, dataset_name=NULL, script, drivers, output_variable){ + env <- new.env() + analytical_drivers <- fromJSON(drivers) + env$drivers_ <- analytical_drivers + script <- resolve_drivers(script, analytical_drivers) + if (!is.null(dataset_name)) { + script <- gsub(dataset_name,"df_",script) + env$df_ <- as.data.frame(fromJSON(dataset)) + } + script <- gsub(output_variable,"env$output_variable_",script) + eval(parse(text=script), envir = env) + html <- env$output_variable_ + html +} + +#' @post /dataset +function(script, df_name, parameters){ + env <- new.env() + token <- decode_jwt_token(script) + if (!is_dataset_request_authorized(token)) + stop("Unauthorized") + decoded_script <- get_script_from_token(token) + env$parameters_ <- build_parameters(parameters) + decoded_script <- resolve_parameters(decoded_script, env$parameters_) + decoded_script <- gsub(df_name, "df_", decoded_script) + env$df_ <- data.frame() + eval(parse(text=decoded_script), envir = env) + env$df_ +} + +#' @get /libraries +#' @get /dataset/libraries +function(){ + lib <- get_libraries() + lib +} diff --git a/ROADMAP.md b/ROADMAP.md index 122fecaff71..90c8d7bb610 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -39,9 +39,7 @@ The following list of features is planned to be addressed in the short term, by The following list of features is planned to be addressed in the medium term, by Q2 2020 (release 7.3): -* from data exploration tool (QbE) to cockpit designer in a seamless way - -* AWS S3 compatibility +* from data exploration tool (QbE) to cockpit designer in a seamless way * NGSI-LD compatibility diff --git a/cas/src/main/webapp/META-INF/context.xml b/cas/src/main/webapp/META-INF/context.xml index 04045cdb824..9dd85af13ef 100644 --- a/cas/src/main/webapp/META-INF/context.xml +++ b/cas/src/main/webapp/META-INF/context.xml @@ -1,4 +1,5 @@ - - + + + diff --git a/knowage-ce-parent/pom.xml b/knowage-ce-parent/pom.xml index 817773d7374..97cd6f02b2e 100644 --- a/knowage-ce-parent/pom.xml +++ b/knowage-ce-parent/pom.xml @@ -24,15 +24,16 @@ https://www.license4j.com/maven/ default - - - boundlessgeo.com - https://repo.boundlessgeo.com/main/ - + osgeo.org - http://download.osgeo.org/webdav/geotools/ + https://repo.osgeo.org/repository/release/ + + + + geo-solutions + https://maven.geo-solutions.it/ @@ -99,6 +100,7 @@ ../knowage-core ../knowageoauth2securityprovider ../knowageldapsecurityprovider + ../knowagegooglesecurityprovider ../knowage ../slimerjs-wrapper ../knowagecockpitengine diff --git a/knowage-core/pom.xml b/knowage-core/pom.xml index 0b4fde74c26..68666c6fe5c 100644 --- a/knowage-core/pom.xml +++ b/knowage-core/pom.xml @@ -90,6 +90,7 @@ compile + com.wealdtech.hawk hawk-core @@ -111,6 +112,7 @@ + org.apache.xmlgraphics batik-transcoder diff --git a/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RUtils.java b/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RUtils.java new file mode 100644 index 00000000000..26865a0a1da --- /dev/null +++ b/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RUtils.java @@ -0,0 +1,134 @@ +package it.eng.knowage.backendservices.rest.widgets; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.codec.binary.Base64; +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONObject; + +import it.eng.spagobi.api.v2.ConfigResource; +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; +import it.eng.spagobi.utilities.rest.RestUtilities.Response; + +public class RUtils { + + static protected Logger logger = Logger.getLogger(RUtils.class); + + private RUtils() { + } + + static String getFinalResult(Response rEngineResponse, String outputType) { + String rString = rEngineResponse.getResponseBody(); + String rOutput = rString.substring(2, rString.length() - 2); + if (outputType.equals("img")) { + return ""; + } else { + return rOutput; + } + } + + static HashMap createDriversMap(String driversString) { + HashMap driversMap = new HashMap(); + try { + JSONObject driversJSON = new JSONObject(driversString); + Iterator keys = driversJSON.keys(); + while (keys.hasNext()) { + String key = keys.next(); + String value = driversJSON.getString(key); + driversMap.put(key, value); + } + } catch (Exception e) { + logger.error("error while creating parameters map"); + throw new SpagoBIRuntimeException("error while creating parameters map", e); + } + return driversMap; + } + + static String DataSet2DataFrame(String knowageDs) { + JSONObject oldDataset; + JSONArray newDataframe = new JSONArray(); + try { + oldDataset = new JSONObject(knowageDs); + Map columnNames = new HashMap(); + JSONObject metaData = oldDataset.getJSONObject("metaData"); + JSONArray fields = (JSONArray) metaData.get("fields"); + for (int i = 1; i < fields.length(); i++) { + JSONObject col = fields.getJSONObject(i); + columnNames.put(col.get("name").toString(), col.get("header").toString()); + } + JSONArray rows = (JSONArray) oldDataset.get("rows"); + for (int j = 0; j < rows.length(); j++) { + JSONObject row = rows.getJSONObject(j); + Iterator keys = row.keys(); + JSONObject newDataframeRow = new JSONObject(); + while (keys.hasNext()) { + String key = keys.next(); + if (columnNames.get(key) != null) { + newDataframeRow.put(columnNames.get(key), row.get(key)); + } + } + newDataframe.put(newDataframeRow); + } + } catch (Exception e) { + logger.error("error while converting json to dataframe format"); + throw new SpagoBIRuntimeException("error while converting json to dataframe format", e); + } + return newDataframe.toString(); + } + + static String getRAddress(String envLabel) { + ConfigResource configResource = new ConfigResource(); + List allRConfigs = configResource.getConfigsByCategory("R_CONFIGURATION"); + for (Config cfg : allRConfigs) { + if (cfg.getLabel().equals(envLabel)) { + return "http://" + cfg.getValueCheck() + "/"; + } + } + throw new SpagoBIRuntimeException("Cannot retrieve R address from label [" + envLabel + "]"); + } + + static String createREngineRequestBody(String dataset, String dsLabel, String script, String driversAsString, String outputVariable) { + JSONObject jsonBody = new JSONObject(); + try { + jsonBody.put("dataset", dataset); + jsonBody.put("script", script); + jsonBody.put("output_variable", outputVariable); + jsonBody.put("dataset_name", dsLabel); + jsonBody.put("drivers", driversAsString); + } catch (Exception e) { + logger.error("error while creating request body for R engine"); + throw new SpagoBIRuntimeException("error while creating request body for R engine", e); + } + return jsonBody.toString(); + } + + static String getRCodeFromTemplate(String base64template, String widgetId) { + JSONObject templateJson; + try { + byte[] decodedBytes = Base64.decodeBase64(base64template); + String template = new String(decodedBytes, "UTF-8"); + templateJson = new JSONObject(new String(decodedBytes, "UTF-8")); + JSONArray sheets = (JSONArray) templateJson.get("sheets"); + for (int i = 0; i < sheets.length(); i++) { + JSONObject sheet = sheets.getJSONObject(i); + JSONArray widgets = (JSONArray) sheet.get("widgets"); + for (int j = 0; j < widgets.length(); j++) { + JSONObject widget = widgets.getJSONObject(j); + String id = widget.getString("id"); + if (id.equals(widgetId)) { + return widget.get("RCode").toString(); + } + } + } + } catch (Exception e) { + logger.error("error while retrieving code from template"); + throw new SpagoBIRuntimeException("error while retrieving code from template", e); + } + throw new SpagoBIRuntimeException("Couldn't retrieve code from template for widgetId [" + widgetId + "]"); + } +} diff --git a/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RWidgetProxy.java b/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RWidgetProxy.java new file mode 100644 index 00000000000..b3127be4b4c --- /dev/null +++ b/knowage-core/src/main/java/it/eng/knowage/backendservices/rest/widgets/RWidgetProxy.java @@ -0,0 +1,197 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2019 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.backendservices.rest.widgets; + +import java.util.HashMap; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.apache.log4j.Logger; +import org.json.JSONObject; + +import it.eng.spagobi.api.common.AbstractDataSetResource; +import it.eng.spagobi.commons.bo.UserProfile; +import it.eng.spagobi.commons.constants.SpagoBIConstants; +import it.eng.spagobi.services.content.service.ContentServiceImplSupplier; +import it.eng.spagobi.services.rest.annotations.UserConstraint; +import it.eng.spagobi.user.UserProfileManager; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; +import it.eng.spagobi.utilities.rest.RestUtilities; +import it.eng.spagobi.utilities.rest.RestUtilities.HttpMethod; + +/* + https://localhost:8080/knowage/restful-services/2.0/backendservices/widgets/RWidget + */ + +@Path("/2.0/backendservices/widgets/RWidget") +public class RWidgetProxy extends AbstractDataSetResource { + + Map headers; + HttpMethod methodPost = HttpMethod.valueOf("Post"); + HttpMethod methodGet = HttpMethod.valueOf("Get"); + + static protected Logger logger = Logger.getLogger(RWidgetProxy.class); + + @POST + @Path("/view/{output_type}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public Response view(@PathParam("output_type") String outputType, HashMap requestBody) { + logger.debug("IN"); + UserProfile userProfile = UserProfileManager.getProfile(); + String userId = (String) userProfile.getUserUniqueIdentifier(); + ContentServiceImplSupplier supplier = new ContentServiceImplSupplier(); + HashMap drivers; + String script = null, documentId = null, outputVariable = null, dsLabel = null, parameters = null, aggregations = null, selections = null, + widgetId = null, envLabel = null, driversAsString = null; + try { + envLabel = requestBody.get("r_environment"); + dsLabel = requestBody.get("dataset"); + documentId = requestBody.get("document_id"); + widgetId = requestBody.get("widget_id"); + outputVariable = requestBody.get("output_variable"); + parameters = requestBody.get("parameters"); + driversAsString = requestBody.get("drivers"); + drivers = RUtils.createDriversMap(driversAsString); + aggregations = requestBody.get("aggregations"); + selections = requestBody.get("selections"); + script = RUtils.getRCodeFromTemplate(supplier.readTemplate(userId, documentId, drivers).getContent(), widgetId); + } catch (Exception e) { + logger.error("error while retrieving request information for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while retrieving request information for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + String rDataframe = null; + if (dsLabel != null) { + String knowageDs = getDataStore(dsLabel, parameters, drivers, selections, null, -1, aggregations, null, -1, -1, false, null, null); + rDataframe = RUtils.DataSet2DataFrame(knowageDs); + } + it.eng.spagobi.utilities.rest.RestUtilities.Response rEngineResponse = null; + try { + String body = RUtils.createREngineRequestBody(rDataframe, dsLabel, script, driversAsString, outputVariable); + String rAddress = RUtils.getRAddress(envLabel); + rEngineResponse = RestUtilities.makeRequest(methodPost, rAddress + outputType, headers, body); + } catch (Exception e) { + logger.error("error while making request to R engine for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while making request to R engine for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + if (rEngineResponse == null || rEngineResponse.getStatusCode() != 200) { + return Response.status(400).build(); + } else { + JSONObject toReturn; + try { + toReturn = new JSONObject().put("result", RUtils.getFinalResult(rEngineResponse, outputType)); + } catch (Exception e) { + logger.error("error while creating response json for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while creating response json for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + return Response.ok(toReturn.toString()).build(); + } + } + + @POST + @Path("/edit/{output_type}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + @UserConstraint(functionalities = { SpagoBIConstants.EDIT_PYTHON_SCRIPTS }) + public Response edit(@PathParam("output_type") String outputType, HashMap requestBody) { + logger.debug("IN"); + UserProfile userProfile = UserProfileManager.getProfile(); + String userId = (String) userProfile.getUserUniqueIdentifier(); + HashMap drivers; + String script = null, documentId = null, outputVariable = null, dsLabel = null, parameters = null, aggregations = null, selections = null, + envLabel = null, driversAsString = null; + try { + envLabel = requestBody.get("r_environment"); + dsLabel = requestBody.get("dataset"); + documentId = requestBody.get("document_id"); + outputVariable = requestBody.get("output_variable"); + parameters = requestBody.get("parameters"); + driversAsString = requestBody.get("drivers"); + drivers = RUtils.createDriversMap(driversAsString); + aggregations = requestBody.get("aggregations"); + selections = requestBody.get("selections"); + script = requestBody.get("script"); + } catch (Exception e) { + logger.error("error while retrieving request information for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while retrieving request information for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + String rDataframe = null; + if (dsLabel != null) { + String knowageDs = getDataStore(dsLabel, parameters, drivers, selections, null, -1, aggregations, null, -1, -1, false, null, null); + rDataframe = RUtils.DataSet2DataFrame(knowageDs); + } + it.eng.spagobi.utilities.rest.RestUtilities.Response rEngineResponse = null; + try { + String body = RUtils.createREngineRequestBody(rDataframe, dsLabel, script, driversAsString, outputVariable); + String rAddress = RUtils.getRAddress(envLabel); + rEngineResponse = RestUtilities.makeRequest(methodPost, rAddress + outputType, headers, body); + } catch (Exception e) { + logger.error("error while making request to R engine for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while making request to R engine for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + if (rEngineResponse == null || rEngineResponse.getStatusCode() != 200) { + return Response.status(400).build(); + } else { + JSONObject toReturn; + try { + toReturn = new JSONObject().put("result", RUtils.getFinalResult(rEngineResponse, outputType)); + } catch (Exception e) { + logger.error("error while creating response json for userId [" + userId + "] and documentId [" + documentId + "]"); + throw new SpagoBIRuntimeException("error while creating response json for userId [" + userId + "] and documentId [" + documentId + "]", e); + } + return Response.ok(toReturn.toString()).build(); + } + } + + @GET + @Path("/libraries/{env_label}") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + @UserConstraint(functionalities = { SpagoBIConstants.EDIT_PYTHON_SCRIPTS }) + public Response libraries(@PathParam("env_label") String envLabel) { + logger.debug("IN"); + it.eng.spagobi.utilities.rest.RestUtilities.Response rEngineResponse = null; + try { + String rAddress = RUtils.getRAddress(envLabel); + rEngineResponse = RestUtilities.makeRequest(methodGet, rAddress + "libraries", headers, null); + } catch (Exception e) { + logger.error("cannot retrieve list of available libraries from R engine"); + throw new SpagoBIRuntimeException("cannot retrieve list of available libraries from R engine", e); + } + if (rEngineResponse == null || rEngineResponse.getStatusCode() != 200) { + return Response.status(400).build(); + } else { + JSONObject toReturn; + try { + toReturn = new JSONObject().put("result", rEngineResponse.getResponseBody()); + } catch (Exception e) { + logger.error("error while creating response json containing available R libraries"); + throw new SpagoBIRuntimeException("error while creating response json containing available R libraries", e); + } + return Response.ok(toReturn.toString()).build(); + } + } +} diff --git a/knowage-core/src/main/java/it/eng/knowage/document/export/cockpit/converter/CommonJSON.java b/knowage-core/src/main/java/it/eng/knowage/document/export/cockpit/converter/CommonJSON.java index 65306c0b48e..459c3c18cc7 100644 --- a/knowage-core/src/main/java/it/eng/knowage/document/export/cockpit/converter/CommonJSON.java +++ b/knowage-core/src/main/java/it/eng/knowage/document/export/cockpit/converter/CommonJSON.java @@ -102,7 +102,7 @@ protected String getColumnName(JSONObject jsonObject, Map column return getColumnAlias(jsonObject, columnAliasToName); } else { - if (jsonObject.has("datasetOrTableFlag")) { + if (jsonObject.has("formula")) { // it is a calculated field return jsonObject.getString("columnName"); } @@ -136,9 +136,10 @@ protected Projection getProjectionWithFunct(IDataSet dataSet, JSONObject jsonObj String columnAlias = getColumnAlias(jsonObject, columnAliasToName); IAggregationFunction function = AggregationFunctions.get(functName); String functionColumnName = jsonObject.optString("functColumn"); - Projection projection; - if (jsonObject.has("datasetOrTableFlag") && !jsonObject.getBoolean("datasetOrTableFlag")) + if (jsonObject.has("formula")) { function = AggregationFunctions.get("NONE"); + } + Projection projection; if (!function.equals(AggregationFunctions.COUNT_FUNCTION) && functionColumnName != null && !functionColumnName.isEmpty()) { Projection aggregatedProjection = new Projection(dataSet, functionColumnName); projection = new CoupledProjection(function, aggregatedProjection, dataSet, columnName, columnAlias); diff --git a/knowage-core/src/main/java/it/eng/knowage/menu/api/MenuManagementAPI.java b/knowage-core/src/main/java/it/eng/knowage/menu/api/MenuManagementAPI.java new file mode 100644 index 00000000000..2e1db5c1de7 --- /dev/null +++ b/knowage-core/src/main/java/it/eng/knowage/menu/api/MenuManagementAPI.java @@ -0,0 +1,77 @@ +package it.eng.knowage.menu.api; + +import java.util.Collection; + +import it.eng.spago.error.EMFInternalError; +import it.eng.spago.error.EMFUserError; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.commons.bo.Role; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IRoleDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; +import it.eng.spagobi.wapp.bo.Menu; +import it.eng.spagobi.wapp.dao.IMenuDAO; + +/** + * + * @author albnale + * @since 2020/06/12 + */ + +public class MenuManagementAPI { + + private IRoleDAO roleDao = null; + private IMenuDAO menuDao = null; + private IEngUserProfile userProfile = null; + + public MenuManagementAPI(IEngUserProfile userProfile) { + this.userProfile = userProfile; + + try { + roleDao = DAOFactory.getRoleDAO(); + roleDao.setUserProfile(userProfile); + + menuDao = DAOFactory.getMenuDAO(); + menuDao.setUserProfile(userProfile); + + } catch (Throwable t) { + throw new SpagoBIRuntimeException("Impossible to instatiate DAO", t); + } + } + + /** + * Method used to check if the menu is allowed for at least one of the user's roles + * + * @param childElem + * @return + * @throws EMFUserError + * @throws EMFInternalError + */ + public boolean isAccessibleMenu(Menu childElem) throws EMFUserError, EMFInternalError { + boolean allowed = false; + try { + Collection roles = userProfile.getRoles(); + for (Object object : roles) { + String roleName = (String) object; + + roleDao = DAOFactory.getRoleDAO(); + Role role = roleDao.loadByName(roleName); + if (role != null) { + menuDao = DAOFactory.getMenuDAO(); + Menu childrenMenu = menuDao.loadMenuByID(childElem.getMenuId(), role.getId()); + + if (childrenMenu != null) { + allowed = true; + break; + } + } + } + } catch (EMFUserError e) { + throw new EMFUserError(e); + } catch (EMFInternalError e) { + throw new EMFInternalError(e); + } + return allowed; + } + +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/LovValue.java b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/LovValue.java index 04f33f5a608..93f847e26de 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/LovValue.java +++ b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/LovValue.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -43,6 +43,6 @@ public String toString() { String valueS = value != null ? value.toString() : ""; String descriptionS = description != null ? description.toString() : ""; - return "DefaultValue [value=" + valueS + ", description=" + descriptionS + "]"; + return "LovValue [value=" + valueS + ", description=" + descriptionS + "]"; } } \ No newline at end of file diff --git a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/defaultvalues/DefaultValuesList.java b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/defaultvalues/DefaultValuesList.java index 22ff4457a33..8751d715249 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/defaultvalues/DefaultValuesList.java +++ b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/bo/defaultvalues/DefaultValuesList.java @@ -38,7 +38,11 @@ public boolean contains(Object value) { Iterator it = this.iterator(); while (it.hasNext()) { LovValue defaultValue = it.next(); - if (defaultValue.toString().equalsIgnoreCase("LovValue [value=, description=]") || defaultValue.getValue().equals(value)) { + if (value == null && defaultValue.getValue() == null) { + logger.debug("Value null is a default value"); + return true; + } + if (defaultValue.getValue() != null && defaultValue.getValue().equals(value)) { logger.debug("Value [" + value + "] is a default value"); return true; } diff --git a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/service/ExecuteAndSendAction.java b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/service/ExecuteAndSendAction.java index a164e369347..b4723e7bede 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/service/ExecuteAndSendAction.java +++ b/knowage-core/src/main/java/it/eng/spagobi/analiticalmodel/execution/service/ExecuteAndSendAction.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,69 +11,63 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.analiticalmodel.execution.service; -import it.eng.spago.base.RequestContainer; -import it.eng.spago.base.SessionContainer; -import it.eng.spago.base.SourceBean; -import it.eng.spago.base.SourceBeanAttribute; -import it.eng.spago.dispatching.action.AbstractHttpAction; -import it.eng.spago.error.EMFErrorHandler; -import it.eng.spago.error.EMFErrorSeverity; -import it.eng.spago.security.IEngUserProfile; -import it.eng.spagobi.analiticalmodel.document.bo.BIObject; -import it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO; -import it.eng.spagobi.analiticalmodel.document.handlers.ExecutionController; -import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.utilities.ExecutionProxy; -import it.eng.spagobi.commons.utilities.StringUtilities; -import it.eng.spagobi.commons.utilities.UserUtilities; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.Security; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; -import java.util.Properties; import java.util.StringTokenizer; import javax.activation.DataHandler; import javax.activation.DataSource; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; +import it.eng.spago.base.RequestContainer; +import it.eng.spago.base.SessionContainer; +import it.eng.spago.base.SourceBean; +import it.eng.spago.base.SourceBeanAttribute; +import it.eng.spago.dispatching.action.AbstractHttpAction; +import it.eng.spago.error.EMFErrorHandler; +import it.eng.spago.error.EMFErrorSeverity; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO; +import it.eng.spagobi.analiticalmodel.document.handlers.ExecutionController; +import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.utilities.ExecutionProxy; +import it.eng.spagobi.commons.utilities.UserUtilities; + public class ExecuteAndSendAction extends AbstractHttpAction { private static transient Logger logger = Logger.getLogger(ExecuteAndSendAction.class); /* * (non-Javadoc) - * + * * @see it.eng.spagobi.commons.services.BaseProfileAction#service(it.eng.spago.base.SourceBean, it.eng.spago.base.SourceBean) */ + @Override public void service(SourceBean request, SourceBean responseSb) throws Exception { logger.debug("IN"); @@ -85,8 +79,6 @@ public void service(SourceBean request, SourceBean responseSb) throws Exception final String ERROR = "20"; final String TONOTFOUND = "90"; String retCode = ""; - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; try { @@ -203,82 +195,13 @@ public void service(SourceBean request, SourceBean responseSb) throws Exception // } end if (execCtrl.directExecution()) { // SEND MAIL - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.useSSL"); - logger.debug(smtphost + " " + smtpport + " use SSL: " + smtpssl); - - // Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort = 25; - - if ((smtphost == null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if ((smtpport == null) || smtpport.trim().equals("")) { - throw new Exception("Smtp PORT not configured"); - } else { - smptPort = Integer.parseInt(smtpport); - } - if ((from == null) || from.trim().equals("")) - from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.from"); - if (login == null || login.trim().equals("")) - login = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.user"); - if (pass == null || pass.trim().equals("")) - pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.password"); - - if ((from == null) || from.trim().equals("")) - throw new Exception("From field missing from input form or not configured"); - - // Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - - Session session = null; - if (StringUtilities.isEmpty(login) || StringUtilities.isEmpty(pass)) { - props.put("mail.smtp.auth", "false"); - session = Session.getInstance(props); - logger.debug("Connecting to mail server without authentication"); - } else { - props.put("mail.smtp.auth", "true"); - Authenticator auth = new SMTPAuthenticator(login, pass); - // SSL Connection - if (smtpssl.equals("true")) { - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - // props.put("mail.smtp.debug", "true"); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath))) { - /* - * Dynamic configuration of trustedstore for CA Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - session = Session.getInstance(props, auth); - // session.setDebug(true); - // session.setDebugOut(null); - logger.debug("Connecting to mail server with authentication"); - } - - logger.debug("properties: mail.smtp.host:" + smtphost + " mail.smtp.port:" + smtpport); + SessionFacade facade = MailSessionBuilder.newInstance() + .usingUserProfile() + .build(); // create a message - Message msg = new MimeMessage(session); - // set the from / to / cc address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + String[] recipients = to.split(","); InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { @@ -317,16 +240,7 @@ public void service(SourceBean request, SourceBean responseSb) throws Exception // send message EMFErrorHandler errorHandler = getErrorHandler(); if (errorHandler.isOKBySeverity(EMFErrorSeverity.ERROR)) { - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(login)) && (!StringUtilities.isEmpty(pass))) { - // USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost, smptPort, login, pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } else { - // Use normal SMTP - Transport.send(msg); - } + facade.sendMessage(msg); retCode = OK; } else { logger.error("Error while executing and sending object " + errorHandler.getStackTrace()); @@ -349,40 +263,29 @@ public void service(SourceBean request, SourceBean responseSb) throws Exception logger.debug("OUT"); } - private class SMTPAuthenticator extends javax.mail.Authenticator { - private String username = ""; - private String password = ""; - - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } - } - private class SchedulerDataSource implements DataSource { byte[] content = null; String name = null; String contentType = null; + @Override public String getContentType() { return contentType; } + @Override public InputStream getInputStream() throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(content); return bais; } + @Override public String getName() { return name; } + @Override public OutputStream getOutputStream() throws IOException { return null; } @@ -397,7 +300,7 @@ public SchedulerDataSource(byte[] content, String contentType, String name) { /** * Add the description to the BIObjectparameters - * + * * @param BIObjectParameters * @param attributes */ @@ -424,7 +327,7 @@ public void setParametersDescription(List BIObjectParameters, /** * Parse a string with the description of the parameter and return a list with description.. This transformation is necessary because the multivalues * parameters - * + * * @param s * the string with the description * @return the list of descriptions diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/CredentialResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/CredentialResource.java index 8cb00c50657..db5de1ceb61 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/CredentialResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/CredentialResource.java @@ -52,7 +52,7 @@ /** * Bean of the data needed to change the password of an user. - * + * * @author Marco Libanori */ class ChangePasswordData { @@ -104,21 +104,20 @@ public void setUserId(String userId) { /** * Credential resource controller. - * - * Manage login and password change procedure to an unauthenticated - * user. - * + * + * Manage login and password change procedure to an unauthenticated user. + * * @author Marco Libanori */ @Path("/credential") public class CredentialResource { - + private static final String DATE_FORMAT = "yyyy-MM-dd"; private static final Logger logger = Logger.getLogger(CredentialResource.class); - + /** * Change password of an user. - * + * * @param data Data needed to change the password * @return HTTP response */ @@ -129,40 +128,34 @@ public class CredentialResource { @PublicService public Response change(final ChangePasswordData data) { - Response response = Response.ok() - .entity(MessageBundle.getMessage("changePwd.pwdChanged")) - .build(); + Response response = Response.ok().entity(MessageBundle.getMessage("changePwd.pwdChanged")).build(); final String userId = data.getUserId(); final String oldPassword = data.getOldPassword(); final String newPassword = data.getNewPassword(); final String newPasswordConfirm = data.getNewPasswordConfirm(); - + if (StringUtils.isEmpty(userId)) { logger.error("Trying to change password with userId"); - response = Response.status(Response.Status.BAD_REQUEST) - .build(); + response = Response.status(Response.Status.BAD_REQUEST).build(); } else { ISbiUserDAO userDao = DAOFactory.getSbiUserDAO(); SbiUser tmpUser = userDao.loadSbiUserByUserId(userId); - - try { - if (PasswordChecker.getInstance() - .isValid(tmpUser, oldPassword, newPassword, newPasswordConfirm)) { - //getting days number for calculate new expiration date + if (PasswordChecker.getInstance().isValid(tmpUser, oldPassword, newPassword, newPasswordConfirm)) { + // getting days number for calculate new expiration date IConfigDAO configDao = DAOFactory.getSbiConfigDAO(); List lstConfigChecks = configDao.loadConfigParametersByProperties(SpagoBIConstants.CHANGEPWD_EXPIRED_TIME); Date beginDate = new Date(); if (lstConfigChecks.size() > 0) { Config check = (Config) lstConfigChecks.get(0); if (check.isActive()) { - //define the new expired date + // define the new expired date SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT); Calendar cal = Calendar.getInstance(); cal.set(beginDate.getYear() + 1900, beginDate.getMonth(), beginDate.getDate()); - //adds n days (getted from db) + // adds n days (getted from db) cal.add(Calendar.DATE, Integer.parseInt(check.getValueCheck())); try { Date endDate = StringUtilities.stringToDate(sdf.format(cal.getTime()), DATE_FORMAT); @@ -175,27 +168,24 @@ public Response change(final ChangePasswordData data) { } } } - tmpUser.setDtLastAccess(beginDate); //reset last access date - tmpUser.setPassword(Password.encriptPassword(newPassword));//SHA encrypt - tmpUser.setFlgPwdBlocked(false); //reset blocking flag + tmpUser.setDtLastAccess(beginDate); // reset last access date + tmpUser.setPassword(Password.encriptPassword(newPassword));// SHA encrypt + tmpUser.setFlgPwdBlocked(false); // reset blocking flag userDao.updateSbiUser(tmpUser, tmpUser.getId()); logger.debug("Updated properties for user with id " + tmpUser.getId() + " - DtLastAccess: " + tmpUser.getDtLastAccess().toString()); } } catch (EMFUserError e) { logger.error("Error during retrieving of user " + userId, e); - response = Response.status(Response.Status.NOT_FOUND) - .entity(e.getDescription()) - .build(); + response = Response.status(Response.Status.NOT_FOUND).entity(e.getDescription()).build(); } catch (Exception e) { logger.error("Error during password change", e); - response = Response.status(Response.Status.INTERNAL_SERVER_ERROR) - .build(); + response = Response.status(Response.Status.INTERNAL_SERVER_ERROR).build(); } - + } - + return response; - + } - + } diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentCRUD.java b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentCRUD.java index 179570cb881..43d4eddce42 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentCRUD.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentCRUD.java @@ -17,23 +17,16 @@ */ package it.eng.spagobi.api; -import java.security.Security; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; -import java.util.Properties; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.GET; @@ -50,6 +43,8 @@ import org.json.JSONException; import org.json.JSONObject; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; /* SpagoBI, the Open Source Business Intelligence suite * Copyright (C) 2012 Engineering Ingegneria Informatica S.p.A. - SpagoBI Competency Center @@ -63,14 +58,12 @@ import it.eng.spagobi.analiticalmodel.execution.service.ExecuteAdHocUtility; import it.eng.spagobi.analiticalmodel.functionalitytree.bo.LowFunctionality; import it.eng.spagobi.analiticalmodel.functionalitytree.dao.ILowFunctionalityDAO; -import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.commons.bo.Domain; import it.eng.spagobi.commons.bo.UserProfile; import it.eng.spagobi.commons.dao.DAOFactory; import it.eng.spagobi.commons.serializer.DocumentsJSONDecorator; import it.eng.spagobi.commons.serializer.SerializationException; import it.eng.spagobi.commons.serializer.SerializerFactory; -import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.commons.utilities.UserUtilities; import it.eng.spagobi.commons.utilities.messages.IMessageBuilder; import it.eng.spagobi.commons.utilities.messages.MessageBuilder; @@ -509,88 +502,15 @@ public JSONObject createJSONResponseDocuments(JSONArray rows) throws JSONExcepti // sending email to emailAddress with passed subject and emailContent private void sendMail(String emailAddress, String subject, String emailContent) throws Exception { - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.useSSL"); - logger.debug(smtphost + " " + smtpport + " use SSL: " + smtpssl); - - // Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort = 25; - - if ((smtphost == null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if ((smtpport == null) || smtpport.trim().equals("")) { - throw new Exception("Smtp host not configured"); - } else { - smptPort = Integer.parseInt(smtpport); - } - - String from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.from"); - if ((from == null) || from.trim().equals("")) - from = "spagobi@eng.it"; - String user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.user"); - if ((user == null) || user.trim().equals("")) { - logger.debug("Smtp user not configured"); - user = null; - } - String pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.password"); - if ((pass == null) || pass.trim().equals("")) { - logger.debug("Smtp password not configured"); - } - - // Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - // Set timeout limit for mail server to respond - props.put("mail.smtp.timeout", "5000"); - props.put("mail.smtp.connectiontimeout", "5000"); - - // open session - Session session = null; - // create autheticator object - Authenticator auth = null; - if (user != null) { - auth = new SMTPAuthenticator(user, pass); - props.put("mail.smtp.auth", "true"); - // SSL Connection - if (smtpssl.equals("true")) { - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath))) { - /* - * Dynamic configuration of trustedstore for CA Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - session = Session.getInstance(props, auth); - logger.info("Session.getInstance(props, auth)"); - - } else { - session = Session.getInstance(props); - logger.info("Session.getInstance(props)"); - } + SessionFacade facade = MailSessionBuilder.newInstance() + .usingUserProfile() + .withTimeout(5000) + .withConnectionTimeout(5000) + .build(); // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + InternetAddress addressTo = new InternetAddress(emailAddress); msg.setRecipient(Message.RecipientType.TO, addressTo); @@ -605,33 +525,10 @@ private void sendMail(String emailAddress, String subject, String emailContent) mp.addBodyPart(mbp1); // add the Multipart to the message msg.setContent(mp); - // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))) { - // USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost, smptPort, user, pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } else { - // Use normal SMTP - Transport.send(msg); - } - } - - private class SMTPAuthenticator extends javax.mail.Authenticator { - private String username = ""; - private String password = ""; - - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } + // send message + facade.sendMessage(msg); - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionSendMail.java b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionSendMail.java index 6fd6f6a7f14..85b37cd07e7 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionSendMail.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/DocumentExecutionSendMail.java @@ -1,41 +1,21 @@ package it.eng.spagobi.api; -import it.eng.spago.base.SourceBeanAttribute; -import it.eng.spago.security.IEngUserProfile; -import it.eng.spagobi.analiticalmodel.document.bo.BIObject; -import it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO; -import it.eng.spagobi.analiticalmodel.document.handlers.ExecutionController; -import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.utilities.ExecutionProxy; -import it.eng.spagobi.commons.utilities.StringUtilities; -import it.eng.spagobi.services.rest.annotations.ManageAuthorization; -import it.eng.spagobi.utilities.rest.RestUtilities; - import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.Security; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.StringTokenizer; import javax.activation.DataHandler; import javax.activation.DataSource; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.POST; @@ -49,6 +29,19 @@ import org.json.JSONException; import org.json.JSONObject; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; +import it.eng.spago.base.SourceBeanAttribute; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO; +import it.eng.spagobi.analiticalmodel.document.handlers.ExecutionController; +import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.utilities.ExecutionProxy; +import it.eng.spagobi.services.rest.annotations.ManageAuthorization; +import it.eng.spagobi.utilities.rest.RestUtilities; + @Path("/1.0/documentexecutionmail") @ManageAuthorization public class DocumentExecutionSendMail extends AbstractSpagoBIResource { @@ -80,8 +73,6 @@ public Response sendMailDocument(@Context HttpServletRequest req) throws IOExcep String ERROR = "Error. Mail not sent"; final String TONOTFOUND = "90"; // String retCode = ""; - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; try { @@ -151,82 +142,15 @@ public Response sendMailDocument(@Context HttpServletRequest req) throws IOExcep // } end if (execCtrl.directExecution()) { // SEND MAIL - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.useSSL"); - logger.debug(smtphost + " " + smtpport + " use SSL: " + smtpssl); - - // Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort = 25; - - if ((smtphost == null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if ((smtpport == null) || smtpport.trim().equals("")) { - throw new Exception("Smtp PORT not configured"); - } else { - smptPort = Integer.parseInt(smtpport); - } - if ((from == null) || from.trim().equals("")) - from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.from"); - if (login == null || login.trim().equals("")) - login = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.user"); - if (pass == null || pass.trim().equals("")) - pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.password"); - - if ((from == null) || from.trim().equals("")) - throw new Exception("From field missing from input form or not configured"); - - // Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - - Session session = null; - if (StringUtilities.isEmpty(login) || StringUtilities.isEmpty(pass)) { - props.put("mail.smtp.auth", "false"); - session = Session.getInstance(props); - logger.debug("Connecting to mail server without authentication"); - } else { - props.put("mail.smtp.auth", "true"); - Authenticator auth = new SMTPAuthenticator(login, pass); - // SSL Connection - if (smtpssl.equals("true")) { - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - // props.put("mail.smtp.debug", "true"); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath))) { - /* - * Dynamic configuration of trustedstore for CA Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - session = Session.getInstance(props, auth); - // session.setDebug(true); - // session.setDebugOut(null); - logger.debug("Connecting to mail server with authentication"); - } - - logger.debug("properties: mail.smtp.host:" + smtphost + " mail.smtp.port:" + smtpport); + SessionFacade facade = MailSessionBuilder.newInstance() + .usingUserProfile() + .overwritingFromAddress(from) + .overwritingUser(login) + .overwritingPassword(pass) + .build(); // create a message - Message msg = new MimeMessage(session); - // set the from / to / cc address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { @@ -264,16 +188,8 @@ public Response sendMailDocument(@Context HttpServletRequest req) throws IOExcep msg.setContent(mp); // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(login)) && (!StringUtilities.isEmpty(pass))) { - // USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost, smptPort, login, pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } else { - // Use normal SMTP - Transport.send(msg); - } + facade.sendMessage(msg); + // retCode = OK; resultAsMap.put("success", "Mail Sent"); @@ -293,21 +209,6 @@ public Response sendMailDocument(@Context HttpServletRequest req) throws IOExcep return Response.ok(resultAsMap).build(); } - private class SMTPAuthenticator extends javax.mail.Authenticator { - private String username = ""; - private String password = ""; - - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } - } - private class SchedulerDataSource implements DataSource { byte[] content = null; diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java b/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java index d2c26878182..03f33bfcd4f 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/SelfServiceDataSetCRUD.java @@ -1819,7 +1819,7 @@ private IMetaData getDatasetMetadata(IDataSet dataSet, IEngUserProfile profile, JSONArray columnsMetadataArray = new JSONArray(); JSONArray datasetMetadataArray = new JSONArray(); - if ((!metadata.equals("")) && (!metadata.equals("[]"))) { + if ((!metadata.equals("")) && (!metadata.equals("[]")) && (!metadata.equals("undefined"))) { metadataObject = JSONUtils.toJSONObject(metadata); columnsMetadataArray = metadataObject.getJSONArray("columns"); datasetMetadataArray = metadataObject.getJSONArray("dataset"); @@ -1963,10 +1963,8 @@ else if (propertyName.equalsIgnoreCase("Type")) { * This is an heuristic to guess the column type of a column in a datastore created with a file dataset. The method analyses just a portion of the entire * datastore so the result is not guaranteed at 100%. * - * @param dataStore - * the datastore to scan - * @param columnIndex - * the index of the column to check + * @param dataStore the datastore to scan + * @param columnIndex the index of the column to check * @return the guessed type of the column */ private String guessColumnType(IDataStore dataStore, int columnIndex) { diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/common/AbstractDataSetResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/common/AbstractDataSetResource.java index 5eaaf313e40..3976fe748fb 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/common/AbstractDataSetResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/common/AbstractDataSetResource.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.validation.ValidationException; @@ -86,6 +87,7 @@ import it.eng.spagobi.tools.dataset.metasql.query.item.MultipleProjectionSimpleFilter; import it.eng.spagobi.tools.dataset.metasql.query.item.Projection; import it.eng.spagobi.tools.dataset.metasql.query.item.SimpleFilter; +import it.eng.spagobi.tools.dataset.metasql.query.item.SimpleSelectionField; import it.eng.spagobi.tools.dataset.metasql.query.item.Sorting; import it.eng.spagobi.tools.dataset.metasql.query.item.UnsatisfiedFilter; import it.eng.spagobi.tools.dataset.utils.DataSetUtilities; @@ -97,6 +99,7 @@ public abstract class AbstractDataSetResource extends AbstractSpagoBIResource { + private static final String REGEX_FIELDS_VALIDATION = "(?:\\\"[a-zA-Z0-9\\-\\_\\s]*\\\")"; static protected Logger logger = Logger.getLogger(AbstractDataSetResource.class); private static final int SOLR_FACETS_DEFAULT_LIMIT = 10; private static final String VALIDATION_OK = "OK"; @@ -417,12 +420,12 @@ private AbstractSelectionField getProjectionWithFunct(IDataSet dataSet, JSONObje IAggregationFunction function = AggregationFunctions.get(functName); String functionColumnName = jsonObject.optString("functColumn"); AbstractSelectionField projection = null; - if (jsonObject.has("datasetOrTableFlag") && !jsonObject.getBoolean("datasetOrTableFlag")) + if (jsonObject.has("formula")) { function = AggregationFunctions.get("NONE"); + } if (!function.equals(AggregationFunctions.COUNT_FUNCTION) && functionColumnName != null && !functionColumnName.isEmpty()) { - if (jsonObject.has("datasetOrTableFlag")) { + if (jsonObject.has("formula")) { String formula = jsonObject.optString("formula"); - String response = validateFormula(formula); DataStoreCalculatedField aggregatedProjection = new DataStoreCalculatedField(dataSet, functionColumnName, formula); projection = new CoupledCalculatedFieldProjection(function, aggregatedProjection, dataSet, columnName, columnAlias); } else { @@ -430,10 +433,8 @@ private AbstractSelectionField getProjectionWithFunct(IDataSet dataSet, JSONObje projection = new CoupledProjection(function, aggregatedProjection, dataSet, columnName, columnAlias); } } else { - if (jsonObject.has("datasetOrTableFlag")) { + if (jsonObject.has("formula")) { String formula = jsonObject.optString("formula"); - String response = validateFormula(formula); - projection = new DataStoreCalculatedField(function, dataSet, columnAlias, columnAlias, formula); } else { projection = new Projection(function, dataSet, columnName, columnAlias); @@ -442,7 +443,10 @@ private AbstractSelectionField getProjectionWithFunct(IDataSet dataSet, JSONObje return projection; } - public String validateFormula(String formula) throws ValidationException { + public String validateFormula(String formula, List columns) throws ValidationException, JSONException { + + validateBrackets(formula); + validateFields(formula, columns); formula = "select ".concat(formula); CharStream inputStream = CharStreams.fromString(formula); @@ -465,6 +469,63 @@ public String validateFormula(String formula) throws ValidationException { return VALIDATION_OK; } + private void validateBrackets(String formula) { + int roundBrackets = 0; + int squareBrackets = 0; + int curlyBrackets = 0; + + for (int i = 0; i < formula.length(); i++) { + switch (formula.charAt(i)) { + case '(': + roundBrackets++; + break; + case ')': + roundBrackets--; + break; + case '[': + squareBrackets++; + break; + case ']': + squareBrackets--; + break; + case '{': + curlyBrackets++; + break; + case '}': + curlyBrackets--; + break; + + default: + break; + } + } + + if (roundBrackets != 0 || squareBrackets != 0 || curlyBrackets != 0) + throw new ValidationException(); + + } + + private void validateFields(String formula, List columns) { + String regex = REGEX_FIELDS_VALIDATION; + Pattern p = Pattern.compile(regex); + Matcher m = p.matcher(formula); + + while (m.find()) { + boolean found = false; + for (SimpleSelectionField simpleSelectionField : columns) { + + if (simpleSelectionField.getName().equals(m.group(0).replace("\"", ""))) { + found = true; + break; + } + } + + if (!found) + throw new ValidationException(); + } + + } + private AbstractSelectionField getProjection(IDataSet dataSet, JSONObject jsonObject, Map columnAliasToName) throws JSONException { return getProjectionWithFunct(dataSet, jsonObject, columnAliasToName, jsonObject.optString("funct")); // caso in cui ci siano facets complesse (coupled // proj) @@ -475,7 +536,7 @@ private String getColumnName(JSONObject jsonObject, Map columnAl return getColumnAlias(jsonObject, columnAliasToName); } else { - if (jsonObject.has("datasetOrTableFlag")) { + if (jsonObject.has("formula")) { // it is a calculated field return jsonObject.getString("formula"); } @@ -603,18 +664,33 @@ private Sorting getSorting(IDataSet dataSet, JSONObject jsonObject, Map getConfigs() { @GET @Path("/category/{category}") - @UserConstraint(functionalities = { SpagoBIConstants.CONFIG_MANAGEMENT }) @Produces(MediaType.APPLICATION_JSON) public List getConfigsByCategory(@PathParam("category") String category) { logger.debug("IN"); @@ -106,7 +106,7 @@ public List getConfigsByCategory(@PathParam("category") String category) private List filterConfigsByCategory(List allConfigs, String category) { ArrayList filteredConfigs = new ArrayList<>(); for (Config cfg : allConfigs) { - if (cfg.getCategory().equals("PYTHON_CONFIGURATION")) { + if (cfg.getCategory().equals(category)) { filteredConfigs.add(cfg); } } @@ -246,6 +246,14 @@ public String getKnowageCalculatedFunctionConfig(@PathParam("dataSourceId") Inte } + @GET + @Path("/EXPORT.LIMITATION") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + public String getExportLimit() { + String limitExport = SingletonConfig.getInstance().getConfigValue("dataset.export.xls.resultsLimit"); + return limitExport; + } + @POST @Path("/") @UserConstraint(functionalities = { SpagoBIConstants.CONFIG_MANAGEMENT }) diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java index 57c16ce9c27..0cd2969a391 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/DataSetResource.java @@ -46,6 +46,7 @@ import javax.ws.rs.core.Response.ResponseBuilder; import org.apache.log4j.Logger; +import org.geotools.data.DataSourceException; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -55,6 +56,7 @@ import it.eng.knowage.commons.security.PathTraversalChecker; import it.eng.qbe.dataset.QbeDataSet; +import it.eng.spago.error.EMFUserError; import it.eng.spagobi.api.common.AbstractDataSetResource; import it.eng.spagobi.commons.constants.SpagoBIConstants; import it.eng.spagobi.commons.dao.DAOFactory; @@ -66,6 +68,8 @@ import it.eng.spagobi.services.rest.annotations.ManageAuthorization; import it.eng.spagobi.services.rest.annotations.UserConstraint; import it.eng.spagobi.services.serialization.JsonConverter; +import it.eng.spagobi.tenant.Tenant; +import it.eng.spagobi.tenant.TenantManager; import it.eng.spagobi.tools.dataset.DatasetManagementAPI; import it.eng.spagobi.tools.dataset.bo.AbstractJDBCDataset; import it.eng.spagobi.tools.dataset.bo.DataSetBasicInfo; @@ -80,6 +84,7 @@ import it.eng.spagobi.tools.dataset.common.datawriter.IDataWriter; import it.eng.spagobi.tools.dataset.common.metadata.IFieldMetaData; import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; +import it.eng.spagobi.tools.dataset.constants.DatasetFunctionsConfig; import it.eng.spagobi.tools.dataset.dao.DataSetFactory; import it.eng.spagobi.tools.dataset.dao.IDataSetDAO; import it.eng.spagobi.tools.dataset.dao.ISbiDataSetDAO; @@ -96,13 +101,16 @@ import it.eng.spagobi.tools.dataset.metasql.query.item.Projection; import it.eng.spagobi.tools.dataset.metasql.query.item.SimpleFilter; import it.eng.spagobi.tools.dataset.metasql.query.item.SimpleFilterOperator; +import it.eng.spagobi.tools.dataset.metasql.query.item.SimpleSelectionField; import it.eng.spagobi.tools.dataset.metasql.query.item.UnaryFilter; import it.eng.spagobi.tools.dataset.metasql.query.item.UnsatisfiedFilter; import it.eng.spagobi.tools.dataset.persist.IPersistedManager; import it.eng.spagobi.tools.dataset.persist.PersistedHDFSManager; import it.eng.spagobi.tools.dataset.persist.PersistedTableManager; import it.eng.spagobi.tools.dataset.utils.DataSetUtilities; +import it.eng.spagobi.tools.datasource.bo.IDataSource; import it.eng.spagobi.tools.datasource.dao.IDataSourceDAO; +import it.eng.spagobi.utilities.database.DataBaseException; import it.eng.spagobi.utilities.database.DataBaseFactory; import it.eng.spagobi.utilities.database.IDataBase; import it.eng.spagobi.utilities.exceptions.SpagoBIRestServiceException; @@ -144,6 +152,52 @@ public String getNotDerivedDataSets(@QueryParam("callback") String callback) { } } + @GET + @Path("/availableFunctions/{dsId}") + @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") + @UserConstraint(functionalities = { SpagoBIConstants.SELF_SERVICE_DATASET_MANAGEMENT }) + public String availableFunctions(@PathParam("dsId") String datasetId, @QueryParam("useCache") boolean useCache) + throws JSONException, DataBaseException, EMFUserError, DataSourceException { + logger.debug("IN"); + + ISbiDataSetDAO dsDAO = DAOFactory.getSbiDataSetDAO(); + + JSONObject jo = new JSONObject(); + + DatasetFunctionsConfig datasetFunctionsConfig = new DatasetFunctionsConfig(); + + if (useCache) { + IDataSourceDAO dataSourceDAO = DAOFactory.getDataSourceDAO(); + IDataSource dataSource = dataSourceDAO.loadDataSourceWriteDefault(); + + if (dataSource == null) + throw new DataSourceException("No data source found for cache"); + + String dataBaseDialect = dataSource.getDialectName(); + List availableFunctions = datasetFunctionsConfig.getAvailableFunctions(dataBaseDialect); + jo.put("availableFunctions", availableFunctions); + + List nullIfFunction = datasetFunctionsConfig.getNullifFunction(dataBaseDialect); + jo.put("nullifFunction", nullIfFunction); + + } else { + Tenant tenantManager = TenantManager.getTenant(); + SbiDataSet sbiDataSet = dsDAO.loadSbiDataSetByIdAndOrganiz(Integer.valueOf(datasetId), tenantManager.getName()); + IDataSet iDataSet = DataSetFactory.toDataSet(sbiDataSet); + IDataBase database = DataBaseFactory.getDataBase(iDataSet.getDataSource()); + String dataBaseDialect = database.getDatabaseDialect().getValue(); + + List availableFunctions = datasetFunctionsConfig.getAvailableFunctions(dataBaseDialect); + jo.put("availableFunctions", availableFunctions); + + List nullIfFunction = datasetFunctionsConfig.getNullifFunction(dataBaseDialect); + jo.put("nullifFunction", nullIfFunction); + } + + logger.debug("OUT"); + return jo.toString(); + } + @GET @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") @UserConstraint(functionalities = { SpagoBIConstants.SELF_SERVICE_DATASET_MANAGEMENT }) @@ -301,6 +355,7 @@ public Response deleteDataset(@PathParam("label") String label) { @GET @Path("/download/file") @Produces(MediaType.APPLICATION_OCTET_STREAM) + @UserConstraint(functionalities = { SpagoBIConstants.DS_SCOPE_USER, SpagoBIConstants.DS_SCOPE_ENTERPRISE }) public Response downloadDataSetFile(@QueryParam("fileName") String fileName, @QueryParam("type") String type) { File file = null; ResponseBuilder response = null; @@ -738,7 +793,7 @@ public String getDataStorePreview(@PathParam("label") String label, String body) throw new SpagoBIRestServiceException(buildLocaleFromSession(), e); } catch (Exception e) { logger.error("Error while previewing dataset " + label, e); - throw new SpagoBIRuntimeException("Error while previewing dataset " + label, e); + throw new SpagoBIRuntimeException("Error while previewing dataset " + label + ". " + e.getMessage(), e); } } @@ -804,9 +859,17 @@ public String validateFormulaJson(String body) { JSONObject jsonBody = new JSONObject(body); formulaString = jsonBody.getString("formula"); + JSONArray columns = jsonBody.getJSONArray("measuresList"); + List l = new ArrayList(); + + for (int i = 0; i < columns.length(); i++) { + SimpleSelectionField a = new SimpleSelectionField(); + a.setName(((JSONObject) columns.get(i)).getString("name")); + l.add(a); + } try { - String toReturn = validateFormula(formulaString); + validateFormula(formulaString, l); JSONObject okResponse = new JSONObject(); okResponse.put("msg", "ok"); return okResponse.toString(); @@ -822,4 +885,5 @@ public String validateFormulaJson(String body) { return null; } + } \ No newline at end of file diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/ExportResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/ExportResource.java index 18c1c808c24..11285b6e844 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/ExportResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/ExportResource.java @@ -56,6 +56,9 @@ import org.quartz.SchedulerException; import org.quartz.impl.StdSchedulerFactory; +import com.jamonapi.Monitor; +import com.jamonapi.MonitorFactory; + import it.eng.spagobi.api.v2.export.Entry; import it.eng.spagobi.api.v2.export.ExportDeleteOldJob; import it.eng.spagobi.api.v2.export.ExportJobBuilder; @@ -103,8 +106,7 @@ public class ExportResource { * * * @return List of {@link Entry} with files exported by logged user - * @throws IOException - * In case of errors during access of the filesystem + * @throws IOException In case of errors during access of the filesystem */ @GET @Path("/dataset") @@ -113,66 +115,79 @@ public List dataset(@DefaultValue("false") @QueryParam("showAll") boolean logger.debug("IN"); + List ret = new ArrayList(); + UserProfile userProfile = UserProfileManager.getProfile(); - String resoursePath = SpagoBIUtilities.getResourcePath(); - java.nio.file.Path perUserExportResourcePath = ExportPathBuilder.getInstance().getPerUserExportResourcePath(resoursePath, userProfile); - List ret = new ArrayList(); - if (Files.isDirectory(perUserExportResourcePath)) { + logger.info("Getting list of exported files for user " + userProfile.getUserId() + "..."); + Monitor totalTime = MonitorFactory.start("Knowage.ExportResource.gettingExportedDatasets.user:" + userProfile.getUserId()); - DirectoryStream userJobDirectory = null; + try { - try { - userJobDirectory = Files.newDirectoryStream(perUserExportResourcePath, new DirectoryStream.Filter() { + String resoursePath = SpagoBIUtilities.getResourcePath(); + java.nio.file.Path perUserExportResourcePath = ExportPathBuilder.getInstance().getPerUserExportResourcePath(resoursePath, userProfile); - @Override - public boolean accept(java.nio.file.Path entry) throws IOException { - return Files.isDirectory(entry); - } - }); + if (Files.isDirectory(perUserExportResourcePath)) { - Iterator iterator = userJobDirectory.iterator(); + DirectoryStream userJobDirectory = null; - while (iterator.hasNext()) { - java.nio.file.Path curr = iterator.next(); - java.nio.file.Path downloadPlaceholderPath = curr.resolve(ExportPathBuilder.DOWNLOADED_PLACEHOLDER_FILENAME); - java.nio.file.Path metadataPath = curr.resolve(ExportPathBuilder.METADATA_FILENAME); - java.nio.file.Path dataPath = curr.resolve(ExportPathBuilder.DATA_FILENAME); + try { + userJobDirectory = Files.newDirectoryStream(perUserExportResourcePath, new DirectoryStream.Filter() { - boolean downloadPlaceholderExist = Files.isRegularFile(downloadPlaceholderPath); + @Override + public boolean accept(java.nio.file.Path entry) throws IOException { + return Files.isDirectory(entry); + } + }); - if (!showAll) { - if (downloadPlaceholderExist) { - continue; + Iterator iterator = userJobDirectory.iterator(); + + while (iterator.hasNext()) { + java.nio.file.Path curr = iterator.next(); + java.nio.file.Path downloadPlaceholderPath = curr.resolve(ExportPathBuilder.DOWNLOADED_PLACEHOLDER_FILENAME); + java.nio.file.Path metadataPath = curr.resolve(ExportPathBuilder.METADATA_FILENAME); + java.nio.file.Path dataPath = curr.resolve(ExportPathBuilder.DATA_FILENAME); + + boolean downloadPlaceholderExist = Files.isRegularFile(downloadPlaceholderPath); + + if (!showAll) { + if (downloadPlaceholderExist) { + continue; + } } - } - if (!Files.isRegularFile(metadataPath)) { - continue; - } + if (!Files.isRegularFile(metadataPath)) { + continue; + } - if (!Files.isRegularFile(dataPath)) { - continue; - } + if (!Files.isRegularFile(dataPath)) { + continue; + } - ExportMetadata metadata = ExportMetadata.readFromJsonFile(metadataPath); + ExportMetadata metadata = ExportMetadata.readFromJsonFile(metadataPath); - Entry entry = new Entry(metadata.getDataSetName(), metadata.getStartDate(), metadata.getId().toString(), downloadPlaceholderExist); + Entry entry = new Entry(metadata.getDataSetName(), metadata.getStartDate(), metadata.getId().toString(), downloadPlaceholderExist); - ret.add(entry); - } + ret.add(entry); + } - } finally { - if (userJobDirectory != null) { - try { - userJobDirectory.close(); - } catch (IOException e) { - // Yes, it's mute! + } finally { + if (userJobDirectory != null) { + try { + userJobDirectory.close(); + } catch (IOException e) { + // Yes, it's mute! + } } } } + + } finally { + totalTime.stop(); } + logger.info("Got list of exported files for user " + userProfile.getUserId()); + logger.debug("OUT"); return ret; @@ -181,10 +196,8 @@ public boolean accept(java.nio.file.Path entry) throws IOException { /** * Schedules an export in CSV format of the dataset in input. * - * @param dataSetId - * Id of the dataset to be exported - * @param body - * JSON that contains drivers and parameters data + * @param dataSetId Id of the dataset to be exported + * @param body JSON that contains drivers and parameters data * @return The job id */ @POST @@ -249,10 +262,8 @@ public Response datasetAsCsv(@PathParam("dataSetId") Integer dataSetId, String b /** * Schedules an export in Excel format of the dataset in input. * - * @param dataSetId - * Id of the dataset to be exported - * @param body - * JSON that contains drivers and parameters data + * @param dataSetId Id of the dataset to be exported + * @param body JSON that contains drivers and parameters data * @return The job id */ @POST @@ -331,8 +342,7 @@ public void deleteAll() { @Override public FileVisitResult postVisitDirectory(java.nio.file.Path dir, IOException exc) throws IOException { /* - * It's not a problem to delete user directory but it's - * not so useful then we can skip it. + * It's not a problem to delete user directory but it's not so useful then we can skip it. */ if (!perUserExportResourcePath.equals(dir)) { Files.delete(dir); @@ -421,8 +431,7 @@ public Response exportCockpitDocumentWidgetData(DocumentExportConf documentExpor /** * Schedula a job to clean old export. * - * @throws SchedulerException - * In case of error during scheduling + * @throws SchedulerException In case of error during scheduling */ private void scheduleCleanUp() throws SchedulerException { diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/LovResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/LovResource.java index d5b3316fcc0..90bcde915cc 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/LovResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/LovResource.java @@ -38,6 +38,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.log4j.LogMF; @@ -409,16 +410,25 @@ public Response post(@javax.ws.rs.core.Context HttpServletRequest req) { modalitiesValueDAO = DAOFactory.getModalitiesValueDAO(); modalitiesValueDAO.setUserProfile(getUserProfile()); ModalitiesValue modVal = toModality(requestBodyJSON); - if (labelControl(modVal.getLabel())) { + + Integer lovId = null; + if (requestBodyJSON.has("id")) + lovId = requestBodyJSON.getInt("id"); + + if (labelControl(lovId, modVal.getLabel())) { logger.error("LOV with same label already exists"); - throw new SpagoBIRestServiceException("", getLocale(), "LOV with same label already exists"); - } - id = modalitiesValueDAO.insertModalitiesValue(modVal); +// throw new SpagoBIRestServiceException("LOV with same label already exists", getLocale(), "LOV with same label already exists"); + + return Response.status(Status.CONFLICT).build(); + } else { + id = modalitiesValueDAO.insertModalitiesValue(modVal); + + logger.debug("OUT: Posting the LOV - done successfully"); - logger.debug("OUT: Posting the LOV - done successfully"); + // int newID = + // modalitiesValueDAO.loadModalitiesValueByLabel(modValue.getLabel()).getId(); - // int newID = - // modalitiesValueDAO.loadModalitiesValueByLabel(modValue.getLabel()).getId(); + } return Response.ok(id).build(); @@ -474,11 +484,22 @@ public Response put(@javax.ws.rs.core.Context HttpServletRequest req) { modalitiesValueDAO.setUserProfile(getUserProfile()); ModalitiesValue modVal = toModality(requestBodyJSON); - modalitiesValueDAO.modifyModalitiesValue(modVal); - logger.debug("OUT: Putting the LOV - done successfully"); + Integer lovId = null; + if (requestBodyJSON.has("id")) + lovId = requestBodyJSON.getInt("id"); + + if (labelControl(lovId, modVal.getLabel())) { + logger.error("LOV with same label already exists"); +// throw new SpagoBIRestServiceException("LOV with same label already exists", getLocale(), "LOV with same label already exists"); + + return Response.status(Status.CONFLICT).build(); + } else { + modalitiesValueDAO.modifyModalitiesValue(modVal); + logger.debug("OUT: Putting the LOV - done successfully"); - return Response.ok().build(); + return Response.ok().build(); + } } catch (Exception exception) { logger.error("Error while putting LOV", exception); @@ -600,7 +621,7 @@ private ModalitiesValue toModality(JSONObject requestBodyJSON) throws EMFUserErr } - public boolean labelControl(String newLabel) { + public boolean labelControl(Integer lovId, String newLabel) { List modalitiesValues = null; IModalitiesValueDAO modalitiesValueDAO = null; @@ -608,7 +629,7 @@ public boolean labelControl(String newLabel) { modalitiesValueDAO = DAOFactory.getModalitiesValueDAO(); modalitiesValues = modalitiesValueDAO.loadAllModalitiesValue(); for (ModalitiesValue lov : modalitiesValues) { - if (lov.getLabel().equalsIgnoreCase(newLabel)) { + if ((lovId == null || (lovId != null && !lovId.equals(lov.getId()))) && lov.getLabel().equalsIgnoreCase(newLabel)) { return true; } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/RolesResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/RolesResource.java index 7f5294303d7..367f8828668 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/RolesResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/RolesResource.java @@ -366,6 +366,7 @@ public Role BOtoRole(RoleBO bo) { role.setAbleToCreateSelfServiceKpi(bo.isAbleToCreateSelfServiceKpi()); role.setAbleToUseFunctionsCatalog(bo.isAbleToUseFunctionsCatalog()); role.setIsAbleToEditPythonScripts(bo.isAbleToEditPythonScripts()); + role.setIsAbleToCreateCustomChart(bo.isAbleToCreateCustomChart()); role.setIsAbleToSaveSubobjects(bo.isAbleToSaveSubobjects()); role.setIsAbleToSeeSubobjects(bo.isAbleToSeeSubobjects()); role.setIsAbleToSeeViewpoints(bo.isAbleToSeeViewpoints()); diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/UserResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/UserResource.java index 9001438d2c6..358c6f0eb53 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/UserResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/UserResource.java @@ -271,9 +271,9 @@ public Response updateUser(@PathParam("id") Integer id, String body) { sbiUser.setFullName(user.getFullName()); sbiUser.setPassword(user.getPassword()); sbiUser.setDefaultRoleId(user.getDefaultRoleId()); - + sbiUser.setFailedLoginAttempts(user.getFailedLoginAttempts()); // This reset the account lock enabled in case of too much failed login attempts - sbiUser.setFailedLoginAttempts(0); +// sbiUser.setFailedLoginAttempts(0); List list = user.getSbiExtUserRoleses(); Set roles = new HashSet(0); diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/DocumentResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/DocumentResource.java index fba255aed35..81c41b74d5e 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/DocumentResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/DocumentResource.java @@ -17,6 +17,7 @@ */ package it.eng.spagobi.api.v2.documentdetails; +import java.util.Iterator; import java.util.List; import javax.ws.rs.Consumes; @@ -47,6 +48,7 @@ import it.eng.spagobi.services.rest.annotations.UserConstraint; import it.eng.spagobi.utilities.assertion.Assert; import it.eng.spagobi.utilities.exceptions.SpagoBIRestServiceException; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; @Path("/2.0/documents1") public class DocumentResource extends AbstractSpagoBIResource { @@ -82,9 +84,18 @@ public BIObject insertDocument(BIObject document) { logger.debug("IN"); IBIObjectDAO documentDao = null; Assert.assertNotNull(document, "Document can not be null"); - document.setCreationUser((String) getUserProfile().getUserId()); + if (documentLabelNameControl(document, "INSERT", "label")) { + logger.error("Error while inserting document. Document with the same label already exists!"); + throw new SpagoBIRuntimeException("Error while inserting document. Document with the same label already exists!"); + } + + if (documentLabelNameControl(document, "INSERT", "name")) { + logger.error("Error while inserting document. Document with the same name already exists!"); + throw new SpagoBIRuntimeException("Error while inserting document. Document with the same name already exists!"); + } + try { documentDao = DAOFactory.getBIObjectDAO(); Integer documentId = documentDao.insertBIObject(document); @@ -165,6 +176,54 @@ public Integer deleteDocument(@PathParam("id") Integer id) { return id; } + private boolean documentLabelNameControl(BIObject document, String operation, String comparator) { + String labelToCheck = document.getLabel(); + String nameToCheck = document.getName(); + List allDocuments = null; + try { + allDocuments = DAOFactory.getBIObjectDAO().loadAllBIObjects(); + } catch (EMFUserError e) { + logger.error("Error loading documents for label testing"); + throw new SpagoBIRestServiceException(getLocale(), e); + } + if (operation.equalsIgnoreCase("INSERT")) { + Iterator it = allDocuments.iterator(); + while (it.hasNext()) { + BIObject aDocument = (BIObject) it.next(); + if (comparator.equalsIgnoreCase("label")) { + String label = aDocument.getLabel(); + if (label.equals(labelToCheck)) { + return true; + } + } else if (comparator.equalsIgnoreCase("name")) { + String name = aDocument.getName(); + if (name.equals(nameToCheck)) { + return true; + } + } + } + } else { + Integer currentId = document.getId(); + Iterator it = allDocuments.iterator(); + while (it.hasNext()) { + BIObject aDocument = (BIObject) it.next(); + Integer id = aDocument.getId(); + if (comparator.equalsIgnoreCase("label")) { + String label = aDocument.getLabel(); + if (label.equals(labelToCheck) && (!id.equals(currentId))) { + return true; + } + } else if (comparator.equalsIgnoreCase("name")) { + String name = aDocument.getName(); + if (name.equals(nameToCheck) && (!id.equals(currentId))) { + return true; + } + } + } + } + return false; + } + @Path("/{id}/drivers") @Consumes("application/json") @Produces("application/json") diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/subresources/TemplateResource.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/subresources/TemplateResource.java index db1bdc97113..b88fa8fc018 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/subresources/TemplateResource.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/documentdetails/subresources/TemplateResource.java @@ -54,7 +54,7 @@ public class TemplateResource extends AbstractSpagoBIResource { public static enum FILETYPE { - json, xml, bin, rptdesign, sbicockpit + json, xml, bin, rptdesign, sbicockpit, jrxml }; static protected Logger logger = Logger.getLogger(TemplateResource.class); @@ -195,20 +195,9 @@ public Response downloadTemplate(@PathParam("templateId") Integer templateId, @P switch (filetype) { case json: case xml: - byteContent = template.getContent(); - response = Response.ok(byteContent); - response.header("Content-Disposition", "attachment; filename=" + filename); - break; case bin: - byteContent = template.getContent(); - response = Response.ok(byteContent); - response.header("Content-Disposition", "attachment; filename=" + filename); - break; + case jrxml: case rptdesign: - byteContent = template.getContent(); - response = Response.ok(byteContent); - response.header("Content-Disposition", "attachment; filename=" + filename); - break; case sbicockpit: byteContent = template.getContent(); response = Response.ok(byteContent); diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/CSVExportJob.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/CSVExportJob.java index 49174995beb..7326fc48840 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/CSVExportJob.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/CSVExportJob.java @@ -22,6 +22,7 @@ import javax.ws.rs.core.StreamingOutput; +import org.apache.log4j.LogMF; import org.apache.log4j.Logger; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -68,7 +69,8 @@ protected void export(JobExecutionContext context) throws JobExecutionException throw new JobExecutionException(e); } - logger.debug("End CSV export for dataSetId " + getDataSetId() + " with id " + getId() + " by user " + getUserProfile().getUserId()); + LogMF.info(logger, "CSV export completed for user {0}. DataSet is {1}. Final file: dimension (in bytes): {2,number}, path: [{3}], ", + this.getUserProfile().getUserId(), this.getDataSet().getLabel(), getDataFile().toFile().length(), getDataFile().toString()); } diff --git a/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/ExcelExportJob.java b/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/ExcelExportJob.java index cc7d59d001e..9f77f465605 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/ExcelExportJob.java +++ b/knowage-core/src/main/java/it/eng/spagobi/api/v2/export/ExcelExportJob.java @@ -25,6 +25,7 @@ import java.text.SimpleDateFormat; import java.util.Date; +import org.apache.log4j.LogMF; import org.apache.log4j.Logger; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CreationHelper; @@ -35,6 +36,7 @@ import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; +import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.tools.dataset.bo.IDataSet; import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; import it.eng.spagobi.tools.dataset.common.datastore.IRecord; @@ -113,9 +115,45 @@ protected void export(JobExecutionContext context) throws JobExecutionException decimalCellStyle.setBorderTop(CellStyle.BORDER_THIN); decimalCellStyle.setAlignment(CellStyle.ALIGN_RIGHT); - // CREATE HEADER SHEET + String limitExp = SingletonConfig.getInstance().getConfigValue("dataset.export.xls.resultsLimit"); + Integer limitExport; + try { + limitExport = Integer.parseInt(limitExp); + } catch (NumberFormatException e) { + String msg = "Export limit cannot be parsed, check if value set for dataset.export.xls.resultsLimit in Configuration Management is numeric"; + logger.error(msg, e); + limitExport = 10000; + } + + dataSet.loadData(0, limitExport, -1); + IDataStore dataStore = dataSet.getDataStore(); + + int resultNumber; + Object propertyRawValue; + propertyRawValue = dataStore.getMetaData().getProperty("resultNumber"); + resultNumber = ((Integer) propertyRawValue).intValue(); + IMetaData dataSetMetadata = dataSet.getMetadata(); - XSSFRow header = sheet.createRow((short) 0); // first row + // CREATE MESSAGE ABOUT LIMIT + if (resultNumber > limitExport) { + String message = "Query results are exceeding configured threshold, therefore only " + limitExport + " were exported."; + XSSFRow messageRow = sheet.createRow((short) 0); // first row + XSSFCell cell = messageRow.createCell(0); + cell.setCellValue(message); + cell.setCellStyle(borderStyleHeader); + } + + // if(resultNumber > limitExport) { + // "Query results are exceeding configured threshold, therefore only " + limitExport + " were exported."; + // } + + // CREATE HEADER SHEET + XSSFRow header; + if (resultNumber > limitExport) { + header = sheet.createRow((short) 1); // second row + } else { + header = sheet.createRow((short) 0); // first row + } if (dataSetMetadata != null && dataSetMetadata.getFieldCount() > 0) { for (int i = 0; i <= dataSetMetadata.getFieldCount() - 1; i++) { XSSFCell cell = header.createCell(i); @@ -123,14 +161,18 @@ protected void export(JobExecutionContext context) throws JobExecutionException cell.setCellStyle(borderStyleHeader); } } + // FILL CELL RECORD - dataSet.loadData(); - IDataStore dataStore = dataSet.getDataStore(); for (int i = 0; i < Integer.MAX_VALUE && i < dataStore.getRecordsCount(); i++) { try { IRecord dataSetRecord = dataStore.getRecordAt(i); - XSSFRow row = sheet.createRow(i + 1); // starting from 2nd row + XSSFRow row; + if (resultNumber > limitExport) { + row = sheet.createRow(i + 2); // starting from 3rd row + } else { + row = sheet.createRow(i + 1); // starting from 2nd row + } for (int k = 0; k <= dataSetRecord.getFields().size() - 1; k++) { Class clazz = dataSetMetadata.getFieldType(k); @@ -192,9 +234,9 @@ protected void export(JobExecutionContext context) throws JobExecutionException logger.error(msg, e); throw new JobExecutionException(msg, e); } finally { -// if (iterator != null) { -// iterator.close(); -// } + // if (iterator != null) { + // iterator.close(); + // } if (exportFileOS != null) { try { exportFileOS.close(); @@ -204,7 +246,8 @@ protected void export(JobExecutionContext context) throws JobExecutionException } } - logger.debug("End Excel export for dataSetId " + getDataSetId() + " with id " + getId() + " by user " + getUserProfile().getUserId()); + LogMF.info(logger, "XLSX export completed for user {0}. DataSet is {1}. Final file: dimension (in bytes): {2,number}, path: [{3}], ", + this.getUserProfile().getUserId(), this.getDataSet().getLabel(), getDataFile().toFile().length(), getDataFile().toString()); } diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowage-core/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..f9f332b160b --- /dev/null +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,99 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.log4j.LogMF; +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.cache.CacheInterface; +import it.eng.spagobi.utilities.cache.ConfigurationCache; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + private static final String CONFIGURATION_MAP = "CONFIGURATION_MAP"; + + private final Lock lock = new ReentrantLock(); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + CacheInterface cache = ConfigurationCache.getCache(); + HashMap configurations = (HashMap) cache.get(CONFIGURATION_MAP); + if (configurations == null) { + lock.lock(); + try { + configurations = (HashMap) cache.get(CONFIGURATION_MAP); + if (configurations == null) { + HashMap newConfiguration = loadConfigurations(); + cache.put(CONFIGURATION_MAP, newConfiguration); + configurations = newConfiguration; + } + } finally { + lock.unlock(); + } + } + String toReturn = configurations.get(key); + LogMF.debug(logger, "GET : [{0}] = [{01]", key, toReturn); + return toReturn; + } + + private HashMap loadConfigurations() { + logger.debug("IN"); + IConfigDAO dao = null; + HashMap configurations = null; + try { + configurations = new HashMap(); + dao = DAOFactory.getSbiConfigDAO(); + List allConfig = dao.loadAllConfigParameters(); + if (allConfig.isEmpty()) { + logger.error("The table sbi_config is EMPTY"); + } + for (Config config : allConfig) { + configurations.put(config.getLabel(), config.getValueCheck() != null ? config.getValueCheck() : ""); + logger.info("Retrieved configuration: " + config.getLabel() + " / " + config.getValueCheck()); + } + } catch (Exception e) { + logger.error("Impossible to get configuration", e); + throw new SpagoBIRuntimeException("Impossible to get configuration", e); + } finally { + logger.debug("OUT"); + } + return configurations; + } + +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowage-core/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index a90b7d9ff5c..00000000000 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } -} diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/deserializer/TriggerXMLDeserializer.java b/knowage-core/src/main/java/it/eng/spagobi/commons/deserializer/TriggerXMLDeserializer.java index 94e4b5d0544..f91352fc12d 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/deserializer/TriggerXMLDeserializer.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/deserializer/TriggerXMLDeserializer.java @@ -140,7 +140,11 @@ public Object deserialize(Object o, Class clazz) throws DeserializationException startTime = deserializeStartTimeAttribute(xml); endTime = deserializeEndTimeAttribute(xml); zonedStartTime = deserializeZonedStartTimeAttribute(xml); - zonedEndTime = deserializeZonedEndTimeAttribute(xml); + try { + zonedEndTime = deserializeZonedEndTimeAttribute(xml); + } catch (NullPointerException e) { + // End time is nullable + } cronString = (String) xml.getAttribute(CRON_STRING); jobName = (String) xml.getAttribute(JOB_NAME); diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/ConfigurationsInitializer.java b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/ConfigurationsInitializer.java index ee1a18d24bb..53188f8d6d9 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/ConfigurationsInitializer.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/ConfigurationsInitializer.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -19,19 +19,14 @@ import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.hibernate.Query; import org.hibernate.Session; -import org.hibernate.Transaction; import it.eng.spago.base.SourceBean; -import it.eng.spago.init.InitializerIFace; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.AbstractHibernateDAO; import it.eng.spagobi.commons.metadata.SbiConfig; import it.eng.spagobi.commons.metadata.SbiDomains; import it.eng.spagobi.commons.utilities.StringUtilities; @@ -49,57 +44,56 @@ public ConfigurationsInitializer() { targetComponentName = "Configurations"; configurationFileName = "it/eng/spagobi/commons/initializers/metadata/config/configs.xml"; } - + + @Override public void init(SourceBean config, Session hibernateSession) { List configurationParameters; Map existingParametersMap; - + logger.debug("IN"); - + try { configurationParameters = parseConfiguration(hibernateSession); - if(configurationParameters == null || configurationParameters.isEmpty()) { + if (configurationParameters == null || configurationParameters.isEmpty()) { return; } logger.debug("Configuration file contains the definition of [" + configurationParameters.size() + "] configuration parameter(s)"); - + existingParametersMap = getConfParametersFromDatabase(hibernateSession); - if(existingParametersMap == null || existingParametersMap.keySet().size() == 0) { + if (existingParametersMap == null || existingParametersMap.keySet().size() == 0) { logger.debug("Database does not contain configuration parameters"); } else { logger.debug("Database contains [" + existingParametersMap.keySet().size() + "] configuration parameter(s)"); } - - for(SbiConfig configurationParameter : configurationParameters) { - if(existingParametersMap.containsKey( configurationParameter.getLabel() )) { + + for (SbiConfig configurationParameter : configurationParameters) { + if (existingParametersMap.containsKey(configurationParameter.getLabel())) { logger.debug("Parameter [" + configurationParameter.getLabel() + "] already present in database"); } else { hibernateSession.save(configurationParameter); - logger.debug("Parameter [" + configurationParameter.getLabel() + "] succesfully saved into database"); + logger.debug("Parameter [" + configurationParameter.getLabel() + "] succesfully saved into database"); } } - - SingletonConfig.getInstance().clearCache(); - + } catch (Throwable t) { throw new SpagoBIRuntimeException("Ab unexpected error occured while initializeng Configurations", t); } finally { logger.debug("OUT"); } } - + private Map getConfParametersFromDatabase(Session hibernateSession) { Map existingParametersMap; - + logger.debug("IN"); - + existingParametersMap = null; try { String hql = "from SbiConfig"; Query hqlQuery = hibernateSession.createQuery(hql); List configurationParametersFromDatabase = hqlQuery.list(); existingParametersMap = new HashMap(); - for(SbiConfig configurationParameterFromDatabase : configurationParametersFromDatabase) { + for (SbiConfig configurationParameterFromDatabase : configurationParametersFromDatabase) { existingParametersMap.put(configurationParameterFromDatabase.getLabel(), configurationParameterFromDatabase); } } catch (Throwable t) { @@ -107,15 +101,15 @@ private Map getConfParametersFromDatabase(Session hibernateSe } finally { logger.debug("OUT"); } - + return existingParametersMap; } - + private List parseConfiguration(Session hibernateSession) { List configurations; - + logger.debug("IN"); - + configurations = new ArrayList(); try { SourceBean configSB = getConfiguration(); @@ -123,33 +117,33 @@ private List parseConfiguration(Session hibernateSession) { logger.info("Configuration file for predefined configuration parameters not found"); return configurations; } - + List configList = configSB.getAttributeAsList("CONFIG"); if (configList == null || configList.isEmpty()) { logger.info("No predefined configuration parameters available from configuration file"); return configurations; } - + for (SourceBean aConfigSB : configList) { SbiDomains hibDomain = null; - + String valueTypeCd = (String) aConfigSB.getAttribute("valueType"); - if ( StringUtilities.isNotEmpty(valueTypeCd ) ){ + if (StringUtilities.isNotEmpty(valueTypeCd)) { hibDomain = findDomain(hibernateSession, valueTypeCd, "PAR_TYPE"); if (hibDomain == null) { logger.error("Could not find domain for configuration parameter"); return configurations; } - } - - String confLabel=((String) aConfigSB.getAttribute("label")); - String confName=((String) aConfigSB.getAttribute("name")); - String confDesc=((String) aConfigSB.getAttribute("description")); - String confIsActive=((String) aConfigSB.getAttribute("isActive")); - String confValueCheck=((String) aConfigSB.getAttribute("valueCheck")); - String confCategory=((String) aConfigSB.getAttribute("category")); - - SbiConfig configuration=new SbiConfig(); + } + + String confLabel = ((String) aConfigSB.getAttribute("label")); + String confName = ((String) aConfigSB.getAttribute("name")); + String confDesc = ((String) aConfigSB.getAttribute("description")); + String confIsActive = ((String) aConfigSB.getAttribute("isActive")); + String confValueCheck = ((String) aConfigSB.getAttribute("valueCheck")); + String confCategory = ((String) aConfigSB.getAttribute("category")); + + SbiConfig configuration = new SbiConfig(); configuration.setLabel(confLabel); configuration.setName(confName); configuration.setDescription(confDesc); @@ -157,18 +151,18 @@ private List parseConfiguration(Session hibernateSession) { configuration.setSbiDomains(hibDomain); configuration.setCategory(confCategory); - Boolean value = confIsActive!=null ? Boolean.valueOf(confIsActive) : Boolean.FALSE; + Boolean value = confIsActive != null ? Boolean.valueOf(confIsActive) : Boolean.FALSE; configuration.setIsActive(value.booleanValue()); - - configurations.add( configuration ); + + configurations.add(configuration); } } catch (Throwable t) { throw new SpagoBIRuntimeException("Ab unexpected error occured while reading configuration parameters from file", t); } finally { logger.debug("OUT"); } - + return configurations; } - + } diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/DataSourceInitializer.java b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/DataSourceInitializer.java new file mode 100644 index 00000000000..e6c9b747f72 --- /dev/null +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/DataSourceInitializer.java @@ -0,0 +1,148 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons.initializers.metadata; + +import java.util.Iterator; +import java.util.List; + +import org.apache.log4j.Logger; +import org.hibernate.Criteria; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.criterion.Restrictions; + +import it.eng.spago.base.SourceBean; +import it.eng.spagobi.commons.metadata.SbiCommonInfo; +import it.eng.spagobi.commons.metadata.SbiDomains; +import it.eng.spagobi.commons.metadata.SbiOrganizationDatasource; +import it.eng.spagobi.commons.metadata.SbiOrganizationDatasourceId; +import it.eng.spagobi.commons.metadata.SbiTenant; +import it.eng.spagobi.commons.utilities.HibernateSessionManager; +import it.eng.spagobi.tools.datasource.metadata.SbiDataSource; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * @author Alberto Nale + * @since 2020/03/31 + */ +public class DataSourceInitializer extends SpagoBIInitializer { + + static private Logger logger = Logger.getLogger(DataSourceInitializer.class); + + public DataSourceInitializer() { + targetComponentName = "DataSource"; + configurationFileName = "it/eng/spagobi/commons/initializers/metadata/config/dataSource.xml"; + } + + @Override + public void init(SourceBean config, Session hibernateSession) { + logger.debug("IN"); + try { + String hql = "from SbiDataSource"; + Query hqlQuery = hibernateSession.createQuery(hql); + List dataSources = hqlQuery.list(); + if (dataSources.isEmpty()) { + logger.info("DataSource table is empty. Starting populating DataSources..."); + writeDefaultDatasources(hibernateSession); + } else { + logger.debug("DataSource table is already populated. No operations needed."); + } + } catch (Throwable t) { + throw new SpagoBIRuntimeException("An unexpected error occured while initializing DataSources", t); + } finally { + logger.debug("OUT"); + } + } + + private void writeDefaultDatasources(Session aSession) throws Exception { + logger.debug("IN"); + SourceBean dataSourcesSB = getConfiguration(); + if (dataSourcesSB == null) { + throw new Exception("DataSources configuration file not found!!!"); + } + List dataSourcesList = dataSourcesSB.getAttributeAsList("DATASOURCE"); + if (dataSourcesList == null || dataSourcesList.isEmpty()) { + throw new Exception("No predefined DataSources found!!!"); + } + + Iterator it = dataSourcesList.iterator(); + while (it.hasNext()) { + SourceBean dataSourceSB = (SourceBean) it.next(); + + String jndi = (String) dataSourceSB.getAttribute("jndi"); + SbiDataSource aDataSource = new SbiDataSource(); + aDataSource.setDescr((String) dataSourceSB.getAttribute("descr")); + aDataSource.setLabel((String) dataSourceSB.getAttribute("label")); + aDataSource.setJndi(jndi); + aDataSource.setUrl_connection((String) dataSourceSB.getAttribute("urlConnection")); + aDataSource.setUser((String) dataSourceSB.getAttribute("username")); + aDataSource.setPwd((String) dataSourceSB.getAttribute("pwd")); + aDataSource.setDriver((String) dataSourceSB.getAttribute("driver")); + + String dialect = HibernateSessionManager.determineDialectFromJNDIResource(jndi); + SbiDomains sbiDomainsDialect = getDialect(aSession, dialect); + if (sbiDomainsDialect == null) { + String defaultDialect = HibernateSessionManager.JDBC_URL_PREFIX_2_DIALECT.get("jdbc:mysql"); + logger.warn("No domain found for dialect [" + dialect + "]. Probably no JNDI resource for ds_cache is defined. Dialect set to " + defaultDialect + + "."); + sbiDomainsDialect = getDialect(aSession, defaultDialect); + } + aDataSource.setDialect(sbiDomainsDialect); + + aDataSource.setMultiSchema(((String) dataSourceSB.getAttribute("multiSchema")).equals("false") ? false : true); + aDataSource.setSchemaAttribute((String) dataSourceSB.getAttribute("attrSchema")); + aDataSource.setReadOnly(((String) dataSourceSB.getAttribute("readOnly")).equals("false") ? false : true); + aDataSource.setWriteDefault(((String) dataSourceSB.getAttribute("writeDefault")).equals("false") ? false : true); + aDataSource.setJdbcPoolConfiguration((String) dataSourceSB.getAttribute("jdbcAdvancedConfiguration")); + + String organization = (String) dataSourceSB.getAttribute("organization"); + SbiCommonInfo sbiCommonInfo = new SbiCommonInfo(); + sbiCommonInfo.setOrganization(organization); + aDataSource.setCommonInfo(sbiCommonInfo); + + logger.debug("Inserting DataSource " + aDataSource.toString() + " ..."); + Integer newId = (Integer) aSession.save(aDataSource); + + SbiTenant tenant = (SbiTenant) aSession.createCriteria(SbiTenant.class).add(Restrictions.eq("name", organization)).uniqueResult(); + + if (tenant == null) + throw new Exception("DataSources configuration tenant not found!!!"); + + SbiOrganizationDatasource sbiOrganizationDatasource = new SbiOrganizationDatasource(); + sbiOrganizationDatasource.setSbiDataSource(aDataSource); + sbiOrganizationDatasource.setSbiOrganizations(tenant); + SbiOrganizationDatasourceId idRel = new SbiOrganizationDatasourceId(); + idRel.setDatasourceId(newId); + idRel.setOrganizationId(tenant.getId()); + sbiOrganizationDatasource.setCommonInfo(sbiCommonInfo); + sbiOrganizationDatasource.setId(idRel); + + aSession.save(sbiOrganizationDatasource); + + } + logger.debug("OUT"); + } + + private SbiDomains getDialect(Session aSession, String dialectString) { + Criteria criteria = aSession.createCriteria(SbiDomains.class); + criteria.add(Restrictions.eq("domainCd", "DIALECT_HIB")); + criteria.add(Restrictions.eq("valueCd", dialectString)); + return (SbiDomains) criteria.uniqueResult(); + } + +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/MetadataInitializer.java b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/MetadataInitializer.java index 9beeeeee212..ff1353f494b 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/MetadataInitializer.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/initializers/metadata/MetadataInitializer.java @@ -17,19 +17,19 @@ */ package it.eng.spagobi.commons.initializers.metadata; -import it.eng.spago.base.SourceBean; - import java.util.ArrayList; import java.util.List; import org.apache.log4j.Logger; import org.hibernate.Session; +import it.eng.spago.base.SourceBean; + /** * @author Zerbetto (davide.zerbetto@eng.it) - * + * * This class initializes SpagoBI metadata repository, if it is empty, with predefined: - * + * * - domains, - checks, - lovs, - engines, - user functionalities **/ public class MetadataInitializer extends SpagoBIInitializer { @@ -47,6 +47,7 @@ public MetadataInitializer() { metadataInitializers.add(new EnginesInitializer()); metadataInitializers.add(new ProductTypesInitializer()); metadataInitializers.add(new TenantsInitializer()); + metadataInitializers.add(new DataSourceInitializer()); metadataInitializers.add(new ChecksInitializer()); metadataInitializers.add(new LovsInitializer()); metadataInitializers.add(new FunctionalitiesInitializer()); diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/serializer/DataSetJSONSerializer.java b/knowage-core/src/main/java/it/eng/spagobi/commons/serializer/DataSetJSONSerializer.java index f82efce0099..2d44eb8653b 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/serializer/DataSetJSONSerializer.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/serializer/DataSetJSONSerializer.java @@ -47,6 +47,7 @@ import it.eng.spagobi.tools.dataset.service.ManageDatasets; import it.eng.spagobi.tools.tag.SbiTag; import it.eng.spagobi.utilities.assertion.Assert; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; import it.eng.spagobi.utilities.json.JSONUtils; public class DataSetJSONSerializer implements Serializer { @@ -435,7 +436,7 @@ public Object serialize(Object o, Locale locale) throws SerializationException { result.put(JCLASS_NAME, jClass); } } else if (type.equalsIgnoreCase(DataSetConstants.FLAT)) { - result.put(DATA_SOURCE_FLAT, jsonConf.getString(DataSetConstants.DATA_SOURCE)); + result.put(DATA_SOURCE_FLAT, jsonConf.getString(DataSetConstants.DATA_SOURCE_FLAT)); result.put(FLAT_TABLE_NAME, jsonConf.getString(DataSetConstants.FLAT_TABLE_NAME)); } else if (DataSetConstants.DS_REST_NAME.equalsIgnoreCase(type)) { manageRESTDataSet(jsonConf, result); @@ -447,7 +448,9 @@ public Object serialize(Object o, Locale locale) throws SerializationException { manageSPARQLDataSet(jsonConf, result); } } catch (Exception e) { - logger.error("Error while defining dataset configuration. Error: " + e.getMessage()); + String msg = "Error while defining dataset configuration."; + logger.error(msg, e); + throw new SpagoBIRuntimeException(msg, e); } result.put(TRASFORMER_TYPE_CD, ds.getTransformerCd()); diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/services/DelegatedQueryExecutor.java b/knowage-core/src/main/java/it/eng/spagobi/commons/services/DelegatedQueryExecutor.java index 96e75f6b37a..21f5b4cc598 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/services/DelegatedQueryExecutor.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/services/DelegatedQueryExecutor.java @@ -27,9 +27,6 @@ import java.util.List; import org.apache.log4j.Logger; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.resolver.DialectResolver; -import org.hibernate.dialect.resolver.StandardDialectResolver; import it.eng.spago.base.RequestContainer; import it.eng.spago.base.ResponseContainer; @@ -48,6 +45,7 @@ import it.eng.spago.util.ContextScooping; import it.eng.spago.util.QueryExecutor; import it.eng.spago.util.StringUtils; +import it.eng.spagobi.commons.utilities.HibernateSessionManager; public class DelegatedQueryExecutor extends QueryExecutor { static private Logger logger = Logger.getLogger(DelegatedQueryExecutor.class); @@ -60,12 +58,9 @@ public class DelegatedQueryExecutor extends QueryExecutor { /** * Creates the command to execute dependent on request type. * - * @param dataConnection - * the data connection - * @param type - * type of query to execute: CREATE, READ, UPDATE, DELETE - * @param statement - * the statement + * @param dataConnection the data connection + * @param type type of query to execute: CREATE, READ, UPDATE, DELETE + * @param statement the statement * @return the SQL command */ public static SQLCommand createStatementSql(final DataConnection dataConnection, final String statement, final String type) { @@ -85,11 +80,9 @@ else if (type.equalsIgnoreCase("DELETE")) /** * Opens the pool connection. * - * @param pool - * the pool + * @param pool the pool * @return the data connection - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public static DataConnection openConnection(final String pool) throws EMFInternalError { return DataConnectionManager.getInstance().getConnection(pool); @@ -98,16 +91,11 @@ public static DataConnection openConnection(final String pool) throws EMFInterna /** * Execs the commands: SQL SELECT, INSERT, DELETE, UPDATE. The connection is gone by the connection pool. * - * @param requestContainer - * the request container - * @param responseContainer - * the response container - * @param pool - * pool's name - * @param query - * the SourceBean that contains the configuration of the query - * @param type - * type of query: CREATE, READ, UPDATE, DELETE + * @param requestContainer the request container + * @param responseContainer the response container + * @param pool pool's name + * @param query the SourceBean that contains the configuration of the query + * @param type type of query: CREATE, READ, UPDATE, DELETE * @return the object */ public static Object executeQuery(final RequestContainer requestContainer, final ResponseContainer responseContainer, final String pool, @@ -135,16 +123,11 @@ public static Object executeQuery(final RequestContainer requestContainer, final /** * Execs the commands: SQL SELECT, INSERT, DELETE, UPDATE. The connection is taken by parameter (for manually transactions) * - * @param requestContainer - * the request container - * @param responseContainer - * the response container - * @param dataConnection - * connection on db - * @param query - * the SourceBean that contains the configuration - * @param type - * type of query: CREATE, READ, UPDATE, DELETE + * @param requestContainer the request container + * @param responseContainer the response container + * @param dataConnection connection on db + * @param query the SourceBean that contains the configuration + * @param type type of query: CREATE, READ, UPDATE, DELETE * @return the object */ public static Object executeQuery(final RequestContainer requestContainer, final ResponseContainer responseContainer, DataConnection dataConnection, @@ -217,17 +200,12 @@ public static Object executeQuery(final RequestContainer requestContainer, final /** * Execs statement SQL with explicit parameters. * - * @param dataConnection - * connection on database: - * @param type - * type of query: CREATE, READ, UPDATE, DELETE - * @param query - * the SourceBean that contains the configuration of the query - * @param parameters - * The parameters to add into statement + * @param dataConnection connection on database: + * @param type type of query: CREATE, READ, UPDATE, DELETE + * @param query the SourceBean that contains the configuration of the query + * @param parameters The parameters to add into statement * @return the object - * @throws Exception - * the exception + * @throws Exception the exception */ public static Object executeQuery(DataConnection dataConnection, String type, SourceBean query, ArrayList parameters) throws Exception { logger.debug("IN"); @@ -349,19 +327,8 @@ protected static boolean handleParameter(final RequestContainer requestContainer Object inParameterValue = null; boolean skipParameterInsertion = false; - DialectResolver resolver = new StandardDialectResolver(); - DatabaseMetaData dbMetadata = null; - try { - Connection connection = dataConnection.getInternalConnection(); - if (connection != null) { - dbMetadata = connection.getMetaData(); - } - } catch (SQLException e) { - logger.error("Error getting database metadata", e); - } - // DialectResolver resolver = new StandardDialectResolver(); - Dialect dialect = resolver.resolveDialect(dbMetadata); + String dialect = HibernateSessionManager.getDialect(); // Set the TRUE value based on the database type if (parameterType.equalsIgnoreCase("TRUE_VALUE")) { @@ -379,7 +346,7 @@ protected static boolean handleParameter(final RequestContainer requestContainer if (dialect != null) { - String dialectName = dialect.toString(); + String dialectName = dialect; if (dialectName.contains("PostgreSQL")) { // inParameterValue = "true"; // add parameter value as SQL TYPE BOOLEAN @@ -391,6 +358,17 @@ protected static boolean handleParameter(final RequestContainer requestContainer } } else { try { + DatabaseMetaData dbMetadata = null; + + try { + Connection connection = dataConnection.getInternalConnection(); + if (connection != null) { + dbMetadata = connection.getMetaData(); + } + } catch (SQLException e) { + logger.error("Error getting database metadata", e); + } + String productName = dbMetadata.getDatabaseProductName(); if (productName.equalsIgnoreCase("oracle")) { inParameterValue = "1"; @@ -415,7 +393,7 @@ protected static boolean handleParameter(final RequestContainer requestContainer else { Object parameterValueObject = ContextScooping.getScopedParameter(requestContainer, responseContainer, parameterValue, parameterScope, parameter); if (parameterValueObject != null) { - if (dialect.toString().contains("PostgreSQL")) { + if (dialect.contains("PostgreSQL")) { // just for Postgres manteins the original value type inParameterValue = parameterValueObject; } else @@ -428,7 +406,7 @@ protected static boolean handleParameter(final RequestContainer requestContainer if (!skipParameterInsertion) { if (!isFilterParameter) { // normal parameter - if (dialect.toString().contains("PostgreSQL")) { + if (dialect.contains("PostgreSQL")) { if (inParameterValue instanceof String) inputParameters.add(dataConnection.createDataField("", Types.VARCHAR, inParameterValue)); else if (inParameterValue instanceof Integer) diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionByToken.java b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionByToken.java index 3be2e903781..7098fc25d3d 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionByToken.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionByToken.java @@ -13,6 +13,7 @@ import it.eng.spago.configuration.ConfigSingleton; import it.eng.spago.security.IEngUserProfile; import it.eng.spagobi.commons.SingletonConfig; +import it.eng.spagobi.commons.bo.SessionUserProfileBuilder; import it.eng.spagobi.commons.bo.UserProfile; import it.eng.spagobi.commons.constants.SpagoBIConstants; import it.eng.spagobi.commons.utilities.AuditLogUtilities; @@ -96,15 +97,15 @@ public void service(SourceBean request, SourceBean response) throws SpagoBIServi if (!isSSOActive) { ISecurityServiceSupplier supplier = SecurityServiceSupplierFactory.createISecurityServiceSupplier(); - Assert.assertNotNull(token, "User identifier not spicified"); + Assert.assertNotNull(token, "Missing authentication token"); SpagoBIUserProfile userProfile = null; userProfile = supplier.checkAuthenticationToken(token); if (userProfile == null) { - logger.warn("An attempt to authenticate with wrong credential has made [" + token + "]"); + logger.error("An attempt to authenticate with token failed: input token is [" + token + "]"); AuditLogUtilities.updateAudit(getHttpRequest(), profile, "LOGIN", null, "KO"); - throw new SpagoBIServiceException(SERVICE_NAME, "An attempt to authenticate with wrong credential has made [" + token + "]"); + throw new SpagoBIServiceException(SERVICE_NAME, "Authentication by token failed"); } // authentication was successful, we get the user unique identifier @@ -127,9 +128,10 @@ public void service(SourceBean request, SourceBean response) throws SpagoBIServi String userId = (String) ((UserProfile) profile).getUserId(); logger.info("User [" + ((UserProfile) profile).getUserId() + "] profile has been loaded succesfully"); - // Propagate user profile - getSessionContainer().getPermanentContainer().setAttribute(IEngUserProfile.ENG_USER_PROFILE, profile); - getHttpRequest().getSession().setAttribute(IEngUserProfile.ENG_USER_PROFILE, profile); + // in case user has a default role, we get his default user profile object + profile = SessionUserProfileBuilder.getDefaultUserProfile((UserProfile) profile); + // put user profile into session + storeProfileInSession((UserProfile) profile, getSessionContainer().getPermanentContainer(), getHttpRequest().getSession()); // Propagate THEME if present if (theme != null && theme.length() > 0) { @@ -161,11 +163,7 @@ public void service(SourceBean request, SourceBean response) throws SpagoBIServi throw new SpagoBIServiceException("Impossible to write back the responce to the client", e); } } catch (Exception t) { - try { - AuditLogUtilities.updateAudit(getHttpRequest(), profile, "LOGIN", null, "KO"); - } catch (Exception e) { - e.printStackTrace(); - } + AuditLogUtilities.updateAudit(getHttpRequest(), profile, "LOGIN", null, "KO"); throw SpagoBIServiceExceptionHandler.getInstance().getWrappedException(SERVICE_NAME, t); } finally { logger.debug("OUT"); diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionWeb.java b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionWeb.java index 7caf86b8c9f..e1aada61bee 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionWeb.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginActionWeb.java @@ -30,6 +30,7 @@ import it.eng.spago.configuration.ConfigSingleton; import it.eng.spago.security.IEngUserProfile; import it.eng.spagobi.commons.SingletonConfig; +import it.eng.spagobi.commons.bo.SessionUserProfileBuilder; import it.eng.spagobi.commons.bo.UserProfile; import it.eng.spagobi.commons.constants.SpagoBIConstants; import it.eng.spagobi.commons.utilities.AuditLogUtilities; @@ -154,9 +155,10 @@ public void service(SourceBean request, SourceBean response) throws SpagoBIServi String userId = (String) ((UserProfile) profile).getUserId(); logger.info("User [" + ((UserProfile) profile).getUserId() + "] profile has been loaded succesfully"); - // Propagate user profile - getSessionContainer().getPermanentContainer().setAttribute(IEngUserProfile.ENG_USER_PROFILE, profile); - getHttpRequest().getSession().setAttribute(IEngUserProfile.ENG_USER_PROFILE, profile); + // in case user has a default role, we get his default user profile object + profile = SessionUserProfileBuilder.getDefaultUserProfile((UserProfile) profile); + // put user profile into session + storeProfileInSession((UserProfile) profile, getSessionContainer().getPermanentContainer(), getHttpRequest().getSession()); // Propagate THEME if present if (theme != null && theme.length() > 0) { @@ -198,4 +200,5 @@ public void service(SourceBean request, SourceBean response) throws SpagoBIServi logger.debug("OUT"); } } + } diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginModule.java b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginModule.java index 2f83250ded1..0adfe4005ea 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginModule.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/services/LoginModule.java @@ -38,6 +38,7 @@ import it.eng.spago.base.RequestContainer; import it.eng.spago.base.SessionContainer; import it.eng.spago.base.SourceBean; +import it.eng.spago.base.SourceBeanException; import it.eng.spago.dispatching.module.AbstractHttpModule; import it.eng.spago.error.EMFErrorHandler; import it.eng.spago.error.EMFErrorSeverity; @@ -62,6 +63,7 @@ import it.eng.spagobi.commons.utilities.messages.MessageBuilder; import it.eng.spagobi.profiling.bean.SbiUser; import it.eng.spagobi.profiling.dao.ISbiUserDAO; +import it.eng.spagobi.security.Password; import it.eng.spagobi.services.common.SsoServiceFactory; import it.eng.spagobi.services.common.SsoServiceInterface; import it.eng.spagobi.services.security.bo.SpagoBIUserProfile; @@ -89,13 +91,10 @@ public class LoginModule extends AbstractHttpModule { /** * Service. * - * @param request - * the request - * @param response - * the response + * @param request the request + * @param response the response * - * @throws Exception - * the exception + * @throws Exception the exception * * @see it.eng.spago.dispatching.action.AbstractHttpAction#service(it.eng.spago.base.SourceBean, it.eng.spago.base.SourceBean) */ @@ -116,6 +115,9 @@ public void service(SourceBean request, SourceBean response) throws Exception { manageLocale(permSess); + MessageBuilder msgBuilder = new MessageBuilder(); + Locale locale = msgBuilder.getLocale(servletRequest); + boolean activeSoo = isSSOActive(); String docLabel = (String) request.getAttribute(SpagoBIConstants.OBJECT_LABEL); @@ -206,7 +208,9 @@ public void service(SourceBean request, SourceBean response) throws Exception { } - boolean isInternalSecurity = ("true".equalsIgnoreCase((String) request.getAttribute("isInternalSecurity"))) ? true : false; +// boolean isInternalSecurity = ("true".equalsIgnoreCase((String) request.getAttribute("isInternalSecurity"))) ? true : false; + String securityServiceSupplier = SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.USER-PROFILE-FACTORY-CLASS.className"); + boolean isInternalSecurity = securityServiceSupplier.equalsIgnoreCase("it.eng.spagobi.security.InternalSecurityServiceSupplierImpl"); logger.debug("isInternalSecurity: " + isInternalSecurity); ISecurityServiceSupplier supplier = SecurityServiceSupplierFactory.createISecurityServiceSupplier(); @@ -215,9 +219,9 @@ public void service(SourceBean request, SourceBean response) throws Exception { // any authentication, just creates the user profile object and puts it into Spago permanent container if (!activeSoo && !isPublicUser) { String pwd = (String) request.getAttribute("password"); + SpagoBIUserProfile userProfile = null; try { - SpagoBIUserProfile userProfile = null; userProfile = supplier.checkAuthentication(userId, pwd); if (userProfile == null) { logger.error("userName/pwd uncorrect"); @@ -234,10 +238,8 @@ public void service(SourceBean request, SourceBean response) throws Exception { AuditLogUtilities.updateAudit(getHttpRequest(), profile, "SPAGOBI.Login", null, "KO"); return; } - } - userIdForDefaultProfile = userId; - userId = userProfile.getUniqueIdentifier(); + } } catch (Exception e) { logger.error("Reading user information... ERROR", e); @@ -274,6 +276,7 @@ public void service(SourceBean request, SourceBean response) throws Exception { boolean goToChangePwd = checkPwd(user); if (goToChangePwd) { + checkIfIsBefore72AuthMethod(response, msgBuilder, locale, user); response.setAttribute("user_id", user.getUserId()); String url = GeneralUtilities.getSpagoBiHost() + servletRequest.getContextPath(); response.setAttribute("start_url", url); @@ -293,6 +296,10 @@ public void service(SourceBean request, SourceBean response) throws Exception { } } } + + userIdForDefaultProfile = userId; + userId = userProfile.getUniqueIdentifier(); + } try { @@ -313,37 +320,43 @@ public void service(SourceBean request, SourceBean response) throws Exception { // checks if the input role is valid with SpagoBI's role list boolean isRoleValid = true; - String checkRoleLogin = SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.CHECK_ROLE_LOGIN"); - if (("true").equals(checkRoleLogin)) { - String roleToCheck = SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN"); - String valueRoleToCheck = ""; - if (!("").equals(roleToCheck)) { - valueRoleToCheck = (request.getAttribute(roleToCheck) != null) ? (String) request.getAttribute(roleToCheck) : ""; - if (!("").equals(valueRoleToCheck)) { - Collection lstRoles = profile.getRoles(); - isRoleValid = false; - Iterator iterRoles = lstRoles.iterator(); - while (iterRoles.hasNext()) { - String iterRoleName = (String) iterRoles.next(); - if (iterRoleName.equals(valueRoleToCheck)) { - isRoleValid = true; - logger.debug("Role in input " + valueRoleToCheck + " is valid. "); - break; + IConfigDAO configDao = DAOFactory.getSbiConfigDAO(); + List checkRoleLoginList = configDao.loadConfigParametersByProperties("SPAGOBI.SECURITY.CHECK_ROLE_LOGIN"); + + if (!checkRoleLoginList.isEmpty()) { + String checkRoleLogin = ((Config) checkRoleLoginList.get(0)).getValueCheck(); + + if (("true").equals(checkRoleLogin)) { + String roleToCheck = SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN"); + String valueRoleToCheck = ""; + if (!("").equals(roleToCheck)) { + valueRoleToCheck = (request.getAttribute(roleToCheck) != null) ? (String) request.getAttribute(roleToCheck) : ""; + if (!("").equals(valueRoleToCheck)) { + Collection lstRoles = profile.getRoles(); + isRoleValid = false; + Iterator iterRoles = lstRoles.iterator(); + while (iterRoles.hasNext()) { + String iterRoleName = (String) iterRoles.next(); + if (iterRoleName.equals(valueRoleToCheck)) { + isRoleValid = true; + logger.debug("Role in input " + valueRoleToCheck + " is valid. "); + break; + } } + } else { + logger.debug("Role " + roleToCheck + " is not passed into the request. Check on the role is not applied. "); } - } else { - logger.debug("Role " + roleToCheck + " is not passed into the request. Check on the role is not applied. "); } - } - if (!isRoleValid) { - logger.error("role uncorrect"); - EMFUserError emfu = new EMFUserError(EMFErrorSeverity.ERROR, 501); - errorHandler.addError(emfu); - AuditLogUtilities.updateAudit(getHttpRequest(), profile, "SPAGOBI.Login", null, "KO"); - // put user role into session - httpSession.setAttribute(roleToCheck, valueRoleToCheck); - response.setAttribute(roleToCheck, valueRoleToCheck); - return; + if (!isRoleValid) { + logger.error("role uncorrect"); + EMFUserError emfu = new EMFUserError(EMFErrorSeverity.ERROR, 501); + errorHandler.addError(emfu); + AuditLogUtilities.updateAudit(getHttpRequest(), profile, "SPAGOBI.Login", null, "KO"); + // put user role into session + httpSession.setAttribute(roleToCheck, valueRoleToCheck); + response.setAttribute(roleToCheck, valueRoleToCheck); + return; + } } } @@ -408,6 +421,13 @@ public void service(SourceBean request, SourceBean response) throws Exception { logger.debug("OUT"); } + private void checkIfIsBefore72AuthMethod(SourceBean response, MessageBuilder msgBuilder, Locale locale, SbiUser user) throws SourceBeanException { + if (user.getPassword().startsWith(Password.PREFIX_SHA_PWD_ENCRIPTING)) { + logger.info("Old encrypting method. Change password required."); + response.setAttribute("old_enc_method_message", msgBuilder.getMessage("old_enc_method_message", "messages", locale)); + } + } + private void storeProfileInSession(UserProfile userProfile, SessionContainer permanentContainer, HttpSession httpSession) { logger.debug("IN"); permanentContainer.setAttribute(IEngUserProfile.ENG_USER_PROFILE, userProfile); @@ -493,6 +513,12 @@ private boolean checkPwd(SbiUser user) throws Exception { boolean toReturn = false; if (user == null) return toReturn; + + if (encriptedBefore72(user)) { + logger.info("Old encrypting method. Change password required."); + return true; + } + Date currentDate = new Date(); // gets the active controls to applicate: @@ -502,7 +528,8 @@ private boolean checkPwd(SbiUser user) throws Exception { for (int i = 0; i < lstConfigChecks.size(); i++) { Config check = (Config) lstConfigChecks.get(i); - if ((SpagoBIConstants.CHANGEPWD_CHANGE_FIRST).equals(check.getLabel()) && user.getDtLastAccess() == null) { + if ((SpagoBIConstants.CHANGEPWD_CHANGE_FIRST).equals(check.getLabel()) && new Boolean(check.getValueCheck()) == true + && user.getDtLastAccess() == null) { // if dtLastAccess isn't enhanced it represents the first login, so is necessary change the pwd logger.info("The pwd needs to activate!"); toReturn = true; @@ -538,6 +565,7 @@ private boolean checkPwd(SbiUser user) throws Exception { break; } } + } // for // general controls: check if the account is already blocked, otherwise update dtLastAccess field @@ -550,4 +578,7 @@ private boolean checkPwd(SbiUser user) throws Exception { return toReturn; } + private boolean encriptedBefore72(SbiUser user) { + return user.getPassword().startsWith(Password.PREFIX_SHA_PWD_ENCRIPTING); + } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/commons/validation/PasswordChecker.java b/knowage-core/src/main/java/it/eng/spagobi/commons/validation/PasswordChecker.java index 299bcd6bd30..f6850744a7f 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/commons/validation/PasswordChecker.java +++ b/knowage-core/src/main/java/it/eng/spagobi/commons/validation/PasswordChecker.java @@ -1,5 +1,11 @@ package it.eng.spagobi.commons.validation; +import java.util.HashMap; +import java.util.List; +import java.util.Vector; + +import org.apache.log4j.Logger; + import it.eng.spago.error.EMFErrorSeverity; import it.eng.spago.error.EMFUserError; import it.eng.spagobi.commons.bo.Config; @@ -9,11 +15,6 @@ import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.profiling.bean.SbiUser; import it.eng.spagobi.security.Password; -import org.apache.log4j.Logger; - -import java.util.HashMap; -import java.util.List; -import java.util.Vector; /** * Password checker singleton. @@ -24,14 +25,14 @@ public class PasswordChecker { private static final String PROP_NODE = "changepwdmodule."; private static final PasswordChecker INSTANCE = new PasswordChecker(); - + private PasswordChecker() { } public static PasswordChecker getInstance() { return INSTANCE; } - + /** * This method checks the syntax of new pwd. * @@ -54,7 +55,7 @@ public boolean isValid(String newPwd, String newPwd2) throws Exception { for (Object lstConfigCheck : configChecks) { Config check = (Config) lstConfigCheck; - + if (check.getValueTypeId() != null && check.getValueCheck() == null) { logger.debug("The value configuration on db isn't valorized."); Vector v = new Vector(); @@ -157,32 +158,33 @@ public boolean isValid(String newPwd, String newPwd2) throws Exception { } return true; - } + } + /** * This method checks the syntax of new pwd. * * @return true if the new password is correct, exception otherwise */ - public boolean isValid(final SbiUser tmpUser, String oldPwd, String newPwd, String newPwd2) throws Exception { + public boolean isValid(final SbiUser tmpUser, String oldPwd, boolean isEncrypted, String newPwd, String newPwd2) throws Exception { IConfigDAO configDao = DAOFactory.getSbiConfigDAO(); List configChecks = configDao.loadConfigParametersByProperties(PROP_NODE); logger.debug("checks found on db: " + configChecks.size()); if (isValid(newPwd, newPwd2)) { - if(oldPwd != null && StringUtilities.isEmpty(oldPwd)) { + if (oldPwd != null && StringUtilities.isEmpty(oldPwd)) { logger.debug("The old password is empty."); throw new EMFUserError(EMFErrorSeverity.ERROR, 14011); } - - if (tmpUser == null || tmpUser != null - && !Password.encriptPassword(oldPwd).equals(tmpUser.getPassword())) { + + String oldPwdEnc = !isEncrypted ? Password.encriptPassword(oldPwd, tmpUser.getPassword().startsWith(Password.PREFIX_SHA_PWD_ENCRIPTING)) : oldPwd; + if (tmpUser == null || tmpUser != null && !oldPwdEnc.equals(tmpUser.getPassword())) { logger.debug("The old pwd is uncorrect."); throw new EMFUserError(EMFErrorSeverity.ERROR, 14010); } - + for (Object lstConfigCheck : configChecks) { Config check = (Config) lstConfigCheck; - + if (check.getLabel().equals(SpagoBIConstants.CHANGEPWDMOD_CHANGE)) { if (oldPwd != null && oldPwd.equalsIgnoreCase(newPwd)) { logger.debug("The password's doesn't be equal the lastest."); @@ -191,7 +193,11 @@ public boolean isValid(final SbiUser tmpUser, String oldPwd, String newPwd, Stri } } } - + return true; } + + public boolean isValid(final SbiUser tmpUser, String oldPwd, String newPwd, String newPwd2) throws Exception { + return isValid(tmpUser, oldPwd, false, newPwd, newPwd2); + } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/engines/drivers/svgviewer/SvgViewerDriver.java b/knowage-core/src/main/java/it/eng/spagobi/engines/drivers/svgviewer/SvgViewerDriver.java index 2d8d0d274a3..38d3b3ddeed 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/engines/drivers/svgviewer/SvgViewerDriver.java +++ b/knowage-core/src/main/java/it/eng/spagobi/engines/drivers/svgviewer/SvgViewerDriver.java @@ -17,19 +17,26 @@ */ package it.eng.spagobi.engines.drivers.svgviewer; +import java.util.ArrayList; +import java.util.List; + +import org.apache.log4j.Logger; +import org.json.JSONException; + +import it.eng.spago.base.SourceBean; +import it.eng.spago.base.SourceBeanException; import it.eng.spagobi.engines.drivers.DefaultOutputParameter; import it.eng.spagobi.engines.drivers.DefaultOutputParameter.TYPE; import it.eng.spagobi.engines.drivers.generic.GenericDriver; -import java.util.ArrayList; -import java.util.List; - /** * @author Marco Cortella (marco.cortella@eng.it) * */ public class SvgViewerDriver extends GenericDriver { + static private Logger logger = Logger.getLogger(SvgViewerDriver.class); + @Override public List getDefaultOutputParameters() { List ret = new ArrayList<>(); @@ -40,4 +47,39 @@ public List getDefaultOutputParameters() { return ret; } + @Override + public ArrayList getDatasetAssociated(byte[] contentTemplate) throws JSONException { + ArrayList associatedDatasets = new ArrayList(); + + SourceBean templateSB = null; + try { + templateSB = SourceBean.fromXMLString(new String(contentTemplate)); + } catch (SourceBeanException e) { + logger.error( + "An error occured while recovering the template, so the relations between document and dataset cannot be inserted. Please check the template uploaded!"); + return null; + } + + // 1. search used datasets + SourceBean dmSB = (SourceBean) templateSB.getAttribute("DATAMART_PROVIDER"); + SourceBean hierarchySB = (SourceBean) dmSB.getAttribute("HIERARCHY"); + + List members = hierarchySB.getAttributeAsList("MEMBER"); + // 3. insert the new relations between document and datasets + + for (int i = 0; i < members.size(); i++) { + SourceBean memberSB = null; + logger.debug("Parsing member [" + i + "]"); + memberSB = (SourceBean) members.get(i); + + String dsLabel = (String) memberSB.getAttribute("measure_dataset"); + logger.debug("Insert relation for dataset with label [" + dsLabel + "]"); + +// VersionedDataSet ds = ((VersionedDataSet) DAOFactory.getDataSetDAO().loadDataSetByLabel(dsLabel)); + // insert only relations with new ds + associatedDatasets.add(dsLabel); + } + return associatedDatasets; + } + } diff --git a/knowage-core/src/main/java/it/eng/spagobi/profiling/services/ManageRolesAction.java b/knowage-core/src/main/java/it/eng/spagobi/profiling/services/ManageRolesAction.java index d4468eab2f0..162001f1f9a 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/profiling/services/ManageRolesAction.java +++ b/knowage-core/src/main/java/it/eng/spagobi/profiling/services/ManageRolesAction.java @@ -69,6 +69,7 @@ public class ManageRolesAction extends AbstractSpagoBIAction { private final String ROLE_TYPE_CD = "typeCd"; private final String CODE = "code"; private final String EDIT_PYTHON_SCRIPTS = "EditPythonScripts"; + private final String CREATE_CUSTOM_CHART = "CreateCustomChart"; private final String SAVE_SUBOBJECTS = "saveSubobj"; private final String SEE_SUBOBJECTS = "seeSubobj"; private final String SEE_VIEWPOINTS = "seeViewpoints"; @@ -169,6 +170,7 @@ public void doService() { String description = getAttributeAsString(DESCRIPTION); Boolean editPythonScripts = getAttributeAsBoolean(EDIT_PYTHON_SCRIPTS); + Boolean createCustomChart = getAttributeAsBoolean(CREATE_CUSTOM_CHART); Boolean saveSubobjects = getAttributeAsBoolean(SAVE_SUBOBJECTS); Boolean seeSubobjects = getAttributeAsBoolean(SEE_SUBOBJECTS); Boolean seeViewpoints = getAttributeAsBoolean(SEE_VIEWPOINTS); @@ -274,6 +276,7 @@ public void doService() { role.setIsAbleToSaveMetadata(saveMetadata); role.setIsAbleToSaveRememberMe(saveRememberMe); role.setIsAbleToEditPythonScripts(editPythonScripts); + role.setIsAbleToCreateCustomChart(createCustomChart); role.setIsAbleToSaveSubobjects(saveSubobjects); role.setIsAbleToSeeMetadata(seeMetadata); role.setIsAbleToSeeNotes(seeNotes); diff --git a/knowage-core/src/main/java/it/eng/spagobi/security/InternalSecurityServiceSupplierImpl.java b/knowage-core/src/main/java/it/eng/spagobi/security/InternalSecurityServiceSupplierImpl.java index 4702f4ef817..88d045eceaa 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/security/InternalSecurityServiceSupplierImpl.java +++ b/knowage-core/src/main/java/it/eng/spagobi/security/InternalSecurityServiceSupplierImpl.java @@ -55,7 +55,7 @@ private SpagoBIUserProfile checkAuthentication(SbiUser user, String userId, Stri try { String password = user.getPassword(); - String encrPass = Password.encriptPassword(psw); + String encrPass = Password.encriptPassword(psw, password.startsWith(Password.PREFIX_SHA_PWD_ENCRIPTING)); if (password == null || password.length() == 0) { logger.error("UserName/pws not defined into database"); return null; diff --git a/knowage-core/src/main/java/it/eng/spagobi/security/init/InternalSecurityInitializer.java b/knowage-core/src/main/java/it/eng/spagobi/security/init/InternalSecurityInitializer.java index 72b512b504b..81165b0f4b2 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/security/init/InternalSecurityInitializer.java +++ b/knowage-core/src/main/java/it/eng/spagobi/security/init/InternalSecurityInitializer.java @@ -27,6 +27,7 @@ import org.apache.log4j.Logger; import org.hibernate.Session; +import org.hibernate.criterion.Restrictions; import it.eng.spago.base.SourceBean; import it.eng.spago.configuration.ConfigSingleton; @@ -41,6 +42,11 @@ import it.eng.spagobi.commons.dao.IRoleDAO; import it.eng.spagobi.commons.initializers.metadata.SpagoBIInitializer; import it.eng.spagobi.commons.metadata.SbiAuthorizations; +import it.eng.spagobi.commons.metadata.SbiAuthorizationsRoles; +import it.eng.spagobi.commons.metadata.SbiAuthorizationsRolesId; +import it.eng.spagobi.commons.metadata.SbiCommonInfo; +import it.eng.spagobi.commons.metadata.SbiDomains; +import it.eng.spagobi.commons.metadata.SbiExtRoles; import it.eng.spagobi.commons.metadata.SbiProductType; import it.eng.spagobi.profiling.bean.SbiAttribute; import it.eng.spagobi.profiling.bean.SbiExtUserRoles; @@ -79,8 +85,10 @@ public void init(SourceBean config, Session hibernateSession) { List attributesList = initProfileAttributes(config); List rolesList = initRoles(config); + initExtRolesCategory(config); Map usersLookupMap = initUsers(config); initDefaultAuthorizations(config); + initDefaultAuthorizationsRoles(config); ISbiUserDAO userDAO = DAOFactory.getSbiUserDAO(); @@ -569,6 +577,139 @@ public void initDefaultAuthorizations(SourceBean config) { return; } + public void initDefaultAuthorizationsRoles(SourceBean config) { + List defaultAuthorizationsRolesSB; + Session aSession = null; + logger.debug("IN"); + try { + Assert.assertNotNull(config, "Input parameter [config] cannot be null"); + defaultAuthorizationsRolesSB = config.getAttributeAsList("DEFAULT_AUTHORIZATIONS_ROLES.AUTHORIZATION_ROLES"); + logger.debug("Succesfully read from configuration [" + defaultAuthorizationsRolesSB.size() + "] defualt authorization(s) roles"); + + List authorizations = null; + List productTypes = null; + + aSession = this.getSession(); + + Map roleNames = new HashMap(); + for (SourceBean defaultAuthorizationSB : defaultAuthorizationsRolesSB) { + roleNames.put((String) defaultAuthorizationSB.getAttribute("roleName"), (String) defaultAuthorizationSB.getAttribute("organization")); + } + + for (String roleName : roleNames.keySet()) { + + IRoleDAO roleDAO = DAOFactory.getRoleDAO(); + String organization = roleNames.get(roleName); + roleDAO.setTenant(organization); + + SbiCommonInfo sbiCommonInfo = new SbiCommonInfo(); + sbiCommonInfo.setOrganization(organization); + + SbiExtRoles role = (SbiExtRoles) aSession.createCriteria(SbiExtRoles.class).add(Restrictions.eq("name", roleName)) + .add(Restrictions.eq("commonInfo.organization", organization)).uniqueResult(); + List authorizationsAlreadyInserted = DAOFactory.getRoleDAO().LoadAuthorizationsAssociatedToRole(role.getExtRoleId()); + + if (authorizationsAlreadyInserted.size() == 0) { + List listOfAuthToInsertForRole = config.getFilteredSourceBeanAttributeAsList("DEFAULT_AUTHORIZATIONS_ROLES.AUTHORIZATION_ROLES", "roleName", + roleName); + + for (Object defaultAuthorization : listOfAuthToInsertForRole) { + SourceBean defaultAuthorizationSB = (SourceBean) defaultAuthorization; + + String authorizationName = (String) defaultAuthorizationSB.getAttribute("authorizationName"); + + if (productTypes == null) + productTypes = DAOFactory.getProductTypeDAO().loadAllProductType(); + + for (SbiProductType productType : productTypes) { + if (authorizations == null) + authorizations = DAOFactory.getRoleDAO().loadAllAuthorizations(); + + SbiAuthorizations sbiAuthorizations = getSbiAuthorizationToInsert(authorizations, authorizationName, + productType.getProductTypeId()); + + if (sbiAuthorizations != null) { + SbiAuthorizationsRoles sbiAuthorizationsRoles = new SbiAuthorizationsRoles(); + sbiAuthorizationsRoles.setId(new SbiAuthorizationsRolesId(sbiAuthorizations.getId(), role.getExtRoleId())); + sbiAuthorizationsRoles.setSbiExtRoles(role); + sbiAuthorizationsRoles.setSbiAuthorizations(sbiAuthorizations); + + sbiAuthorizationsRoles.setCommonInfo(sbiCommonInfo); + aSession.save(sbiAuthorizationsRoles); + } + } + } + } + } + } catch (Throwable t) { + logger.error("An unexpected error occurred while reading defualt profile attibutes", t); + } finally { + if (aSession != null && aSession.isOpen()) { + aSession.close(); + } + logger.debug("OUT"); + } + + } + + private SbiAuthorizations getSbiAuthorizationToInsert(List l, String name, Integer productTypeId) { + SbiAuthorizations toReturn = null; + + for (SbiAuthorizations object : l) { + if (object.getName().equals(name) && object.getProductType().getProductTypeId().equals(productTypeId)) { + toReturn = object; + break; + } + } + + return toReturn; + } + + public void initExtRolesCategory(SourceBean config) { + List extRolesCategoriesSB; + Session aSession = null; + logger.debug("IN"); + try { + Assert.assertNotNull(config, "Input parameter [config] cannot be null"); + extRolesCategoriesSB = config.getAttributeAsList("EXT_ROLES_CATEGORIES.EXT_ROLES_CATEGORY"); + logger.debug("Succesfully read from configuration [" + extRolesCategoriesSB.size() + "] defualt ext roles category(s) roles"); + aSession = this.getSession(); + + Map roleNames = new HashMap(); + for (SourceBean defaultAuthorizationSB : extRolesCategoriesSB) { + roleNames.put((String) defaultAuthorizationSB.getAttribute("roleName"), (String) defaultAuthorizationSB.getAttribute("organization")); + } + + for (String roleName : roleNames.keySet()) { + + String organization = roleNames.get(roleName); + IRoleDAO roleDAO = DAOFactory.getRoleDAO(); + roleDAO.setTenant(organization); + SbiExtRoles role = (SbiExtRoles) aSession.createCriteria(SbiExtRoles.class).add(Restrictions.eq("name", roleName)) + .add(Restrictions.eq("commonInfo.organization", organization)).uniqueResult(); + + if (DAOFactory.getRoleDAO().getMetaModelCategoriesForRole(role.getExtRoleId()).size() == 0) { + for (SourceBean extRolesCategorySB : extRolesCategoriesSB) { + SbiDomains category = (SbiDomains) aSession.createCriteria(SbiDomains.class) + .add(Restrictions.eq("domainCd", extRolesCategorySB.getAttribute("domainCd"))) + .add(Restrictions.isNull("commonInfo.organization")).uniqueResult(); + + roleDAO.insertRoleMetaModelCategory(role.getExtRoleId(), category.getValueId()); + } + } + + } + } catch (Throwable t) { + logger.error("An unexpected error occurred while reading defualt profile attibutes", t); + } finally { + if (aSession != null && aSession.isOpen()) { + aSession.close(); + } + logger.debug("OUT"); + } + + } + private Set loadProductTypes() { List sbiProductTypes = DAOFactory.getProductTypeDAO().loadAllProductType(); if (sbiProductTypes != null && !sbiProductTypes.isEmpty()) { diff --git a/knowage-core/src/main/java/it/eng/spagobi/signup/service/rest/Signup.java b/knowage-core/src/main/java/it/eng/spagobi/signup/service/rest/Signup.java index 89af83f5c50..5b4c9d19c6f 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/signup/service/rest/Signup.java +++ b/knowage-core/src/main/java/it/eng/spagobi/signup/service/rest/Signup.java @@ -19,22 +19,15 @@ import java.io.IOException; import java.net.URL; -import java.security.Security; import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Properties; import java.util.Set; -import javax.mail.Authenticator; import javax.mail.Message; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -56,6 +49,8 @@ import com.google.common.io.Resources; import com.hazelcast.core.IMap; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; import it.eng.spago.error.EMFUserError; import it.eng.spago.security.IEngUserProfile; import it.eng.spagobi.commons.SingletonConfig; @@ -273,7 +268,7 @@ public String update(@Context HttpServletRequest req) { SbiUser user = userDao.loadSbiUserByUserId((String) profile.getUserId()); try { - PasswordChecker.getInstance().isValid(user, user.getPassword(), password, password); + PasswordChecker.getInstance().isValid(user, user.getPassword(), true, password, password); } catch (Exception e) { logger.error("Password is not valid", e); String message = msgBuilder.getMessage("signup.check.pwdInvalid", "messages", locale); @@ -406,7 +401,7 @@ public String active(@Context HttpServletRequest request) throws JSONException { return new JSONObject("{message: '" + msgBuilder.getMessage("signup.msg.userActivationOK", "messages", locale) + "'}").toString(); } catch (TokenExpiredException te) { logger.error("Expired Token [" + token + "]", te); - return new JSONObject("{errors: '" + msgBuilder.getMessage("signup.msg.expiredToken", "messages", locale) + "',expired:true}").toString(); + return new JSONObject("{errors: '" + msgBuilder.getMessage("signup.msg.userActiveKO", "messages", locale) + "',expired:true}").toString(); } catch (Exception e) { logger.error("Generic token validation error [" + token + "]", e); return new JSONObject("{errors: '" + msgBuilder.getMessage("signup.msg.userActiveKO", "messages", locale) + "'}").toString(); @@ -510,10 +505,32 @@ public Response create(@Context HttpServletRequest req) { } ISbiUserDAO userDao = DAOFactory.getSbiUserDAO(); - if (userDao.isUserIdAlreadyInUse(username) != null) { - logger.error("Username already in use"); - JSONObject errObj = buildErrorMessage(msgBuilder, locale, "signup.check.userInUse"); - return Response.ok(errObj.toString()).build(); + Integer existingUserId = userDao.isUserIdAlreadyInUse(username); + boolean userRegistrationFromExpiredToken = false; + /* Match with the username */ + if (existingUserId != null) { + + SbiUser sbiUser = userDao.loadSbiUserById(existingUserId); + /* Check if sbiUser has */ + boolean matchingEmailAddress = false; + if (sbiUser != null) { + Set userAttributes = sbiUser.getSbiUserAttributeses(); + for (SbiUserAttributes sbiUserAttributes : userAttributes) { + if (sbiUserAttributes.getSbiAttribute().getAttributeName().equals("email") && sbiUserAttributes.getAttributeValue().equals(email)) { + matchingEmailAddress = true; + break; + } + } + } + + /* Match with the email address and date from last access */ + userRegistrationFromExpiredToken = matchingEmailAddress && sbiUser.getDtLastAccess() == null; + + if (!userRegistrationFromExpiredToken) { + logger.error("Username already in use"); + JSONObject errObj = buildErrorMessage(msgBuilder, locale, "signup.check.userInUse"); + return Response.ok(errObj.toString()).build(); + } } SbiUser user = new SbiUser(); @@ -525,7 +542,7 @@ public Response create(@Context HttpServletRequest req) { user.setFlgPwdBlocked(true); String defaultTenant = SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.DEFAULT_TENANT_ON_SIGNUP"); - // if config is not defined, because it is a new configurationm do not therow error and put a default value + // if config is not defined, because it is a new configuration do not throw error and put a default value if (defaultTenant == null) { defaultTenant = "DEFAULT_TENANT"; } @@ -569,6 +586,9 @@ public Response create(@Context HttpServletRequest req) { addAttribute(attributes, attrDao.loadSbiAttributeByName("language").getAttributeId(), language); user.setSbiUserAttributeses(attributes); + if (userRegistrationFromExpiredToken) + user.setId(existingUserId); + int id = userDao.fullSaveOrUpdateSbiUser(user); logger.debug("User [" + username + "] succesfuly created with id [" + id + "]"); @@ -593,8 +613,9 @@ public Response create(@Context HttpServletRequest req) { logger.debug("Activation mail's subject set to [" + subject + "]"); String token = SignupJWTTokenManager.createJWTToken(user.getUserId()); + String version = SbiCommonInfo.getVersion().substring(0, SbiCommonInfo.getVersion().lastIndexOf(".")); - String urlString = req.getContextPath() + "/restful-services/signup/prepareActive?token=" + token + "&locale=" + locale; + String urlString = req.getContextPath() + "/restful-services/signup/prepareActive?token=" + token + "&locale=" + locale + "&version=" + version; URL url = new URL(req.getScheme(), host, port, urlString); // Replacing all placeholder occurencies in template with dynamic user values @@ -684,88 +705,15 @@ public void prepare(@Context HttpServletRequest req) { private void sendMail(String emailAddress, String subject, String emailContent) throws Exception { - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.useSSL"); - logger.debug(smtphost + " " + smtpport + " use SSL: " + smtpssl); - - // Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort = 25; - - if ((smtphost == null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if ((smtpport == null) || smtpport.trim().equals("")) { - throw new Exception("Smtp host not configured"); - } else { - smptPort = Integer.parseInt(smtpport); - } - - String from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.from"); - if ((from == null) || from.trim().equals("")) - from = "spagobi@eng.it"; - String user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.user"); - if ((user == null) || user.trim().equals("")) { - logger.debug("Smtp user not configured"); - user = null; - } - String pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.password"); - if ((pass == null) || pass.trim().equals("")) { - logger.debug("Smtp password not configured"); - } - - // Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - // Set timeout limit for mail server to respond - props.put("mail.smtp.timeout", "5000"); - props.put("mail.smtp.connectiontimeout", "5000"); - - // open session - Session session = null; - // create autheticator object - Authenticator auth = null; - if (user != null) { - auth = new SMTPAuthenticator(user, pass); - props.put("mail.smtp.auth", "true"); - // SSL Connection - if (smtpssl.equals("true")) { - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath))) { - /* - * Dynamic configuration of trustedstore for CA Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - session = Session.getInstance(props, auth); - logger.info("Session.getInstance(props, auth)"); - - } else { - session = Session.getInstance(props); - logger.info("Session.getInstance(props)"); - } + SessionFacade facade = MailSessionBuilder.newInstance() + .usingUserProfile() + .withTimeout(5000) + .withConnectionTimeout(5000) + .build(); // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + InternetAddress addressTo = new InternetAddress(emailAddress); msg.setRecipient(Message.RecipientType.TO, addressTo); @@ -781,33 +729,10 @@ private void sendMail(String emailAddress, String subject, String emailContent) // // add the Multipart to the message // msg.setContent(mp); msg.setContent(emailContent, "text/html"); - // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))) { - // USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost, smptPort, user, pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } else { - // Use normal SMTP - Transport.send(msg); - } - - } - private class SMTPAuthenticator extends javax.mail.Authenticator { - private String username = ""; - private String password = ""; - - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } + // send message + facade.sendMessage(msg); - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/DatasetManagementAPI.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/DatasetManagementAPI.java index 9fdf77c9ea8..4a16be0c0e3 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/DatasetManagementAPI.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/DatasetManagementAPI.java @@ -210,12 +210,16 @@ public IDataSet getDataSet(String label) { if (DataSetUtilities.isExecutableByUser(dataSet, getUserProfile()) == false) { Integer dsCategoryId = dataSet.getCategoryId(); + if (dsCategoryId == null) { + throw new RuntimeException("Dataset " + label + " doesn't have category set."); + } // check categories of dataset Set categoryList = UserUtilities.getDataSetCategoriesByUser(getUserProfile()); if (categoryList != null && categoryList.size() > 0) { for (Iterator iterator = categoryList.iterator(); iterator.hasNext();) { Domain domain = (Domain) iterator.next(); Integer domainId = domain.getValueId(); + if (dsCategoryId.equals(domainId)) return dataSet; } @@ -225,7 +229,7 @@ public IDataSet getDataSet(String label) { } return dataSet; } catch (Throwable t) { - throw new RuntimeException("An unexpected error occured while executing method [getDataSet]", t); + throw new RuntimeException("An unexpected error occured while executing method [getDataSet]. " + t.getMessage(), t); } finally { logger.debug("OUT"); } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/associativity/strategy/OuterAssociativityManager.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/associativity/strategy/OuterAssociativityManager.java index 5ef46025e64..7df90828064 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/associativity/strategy/OuterAssociativityManager.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/associativity/strategy/OuterAssociativityManager.java @@ -127,7 +127,7 @@ protected void calculateDatasets(String dataset, EdgeGroup fromEdgeGroup, Simple container.addFilter(filter); } - logger.debug("1. For each associative group of the primary dataset " + container.getDataSet().getLabel() + "do the following:"); +// logger.debug("1. For each associative group of the primary dataset " + container.getDataSet().getLabel() + "do the following:"); Iterator iterator = container.getGroups().iterator(); while (iterator.hasNext()) { EdgeGroup group = iterator.next(); diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/resource/export/ResourceExportFolderCleaningManager.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/resource/export/ResourceExportFolderCleaningManager.java new file mode 100644 index 00000000000..01c2bb2c6b1 --- /dev/null +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/resource/export/ResourceExportFolderCleaningManager.java @@ -0,0 +1,297 @@ +package it.eng.spagobi.tools.dataset.resource.export; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.api.v2.export.ExportPathBuilder; +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.commons.utilities.SpagoBIUtilities; + +public class ResourceExportFolderCleaningManager { + + public static transient Logger logger = Logger.getLogger(ResourceExportFolderCleaningManager.class); + + private static final Long DEFAULT_FOLDER_SIZE = 10737418240L; // 10 GB + private static final Double DEFAULT_CLEANING_PERCENTAGE = 30.0; + + private static final String RESOURCE_EXPORT_FOLDER_SCHED_FULL_CLEAN_CLEANING_PERCENTAGE = "KNOWAGE.RESOURCE.EXPORT.FOLDER.CLEANING_PERCENTAGE"; + private static final String RESOURCE_EXPORT_FOLDER_SCHED_FULL_CLEAN_MAX_FOLDER_SIZE = "KNOWAGE.RESOURCE.EXPORT.FOLDER.MAX_FOLDER_SIZE"; + + private String resourceExportPath = null; + private Long maxResourceFolderSize = DEFAULT_FOLDER_SIZE; + private Double cleaningPrecentage = DEFAULT_CLEANING_PERCENTAGE; + private List allowedFilesNames = new ArrayList(); + + public void executeCleaning(String resourceExportPath, Long maxResourceFolderSize, Double cleaningPrecentage) throws Exception { + this.resourceExportPath = resourceExportPath; + this.maxResourceFolderSize = maxResourceFolderSize; + this.cleaningPrecentage = cleaningPrecentage; + + executeCleaning(false); + } + + public void executeCleaning() throws Exception { + executeCleaning(true); + } + + public void executeCleaning(boolean readPropertiesFromConfig) throws Exception { + logger.debug("IN - executeCleaning"); + + init(); + + if (readPropertiesFromConfig) + resourceExportPath = getExportTempFolderPath(); + + if (resourceExportPath != null && new File(resourceExportPath).exists()) { + + if (readPropertiesFromConfig) { + setMaxResourceFolderSize(); + + setCleaningPrecentage(); + } + + File fileResourceExport = new File(resourceExportPath); + + Long actualFolderSize = folderSize(fileResourceExport); + logger.debug("actualFolderSize (Byte) is " + actualFolderSize); + + if (actualFolderSize > maxResourceFolderSize) { + logger.debug("Cleaning to quota needed"); + cleanToQuota(actualFolderSize, fileResourceExport); + } else { + logger.debug("No cleaning needed"); + } + } else { + String message = "resourceExportPath does not exists"; + logger.info(message); + } + + logger.debug("OUT - executeCleaning"); + } + + private void setCleaningPrecentage() throws Exception { + IConfigDAO sbiConfigDAO = DAOFactory.getSbiConfigDAO(); + Config configValue; + configValue = sbiConfigDAO.loadConfigParametersByLabel(RESOURCE_EXPORT_FOLDER_SCHED_FULL_CLEAN_CLEANING_PERCENTAGE); + if (configValue != null && configValue.isActive()) { + Double tmpPercentage = Double.valueOf(configValue.getValueCheck()); + if (tmpPercentage < 0) + throw new RuntimeException(String.format("cleaningPercentage [%s] not valid", tmpPercentage)); + + cleaningPrecentage = tmpPercentage; + logger.info("Set cleaningPrecentage parameter with value " + cleaningPrecentage); + } else { + logger.info("Set cleaningPrecentage parameter with DEFAULT value " + cleaningPrecentage); + } + } + + private void setMaxResourceFolderSize() throws Exception { + IConfigDAO sbiConfigDAO = DAOFactory.getSbiConfigDAO(); + Config configValue = sbiConfigDAO.loadConfigParametersByLabel(RESOURCE_EXPORT_FOLDER_SCHED_FULL_CLEAN_MAX_FOLDER_SIZE); + if (configValue != null && configValue.isActive()) { + + Long tmpMaxResourceFolderSize = Long.valueOf(configValue.getValueCheck()); + if (tmpMaxResourceFolderSize < 0) + throw new RuntimeException(String.format("maxResourceFolderSize [%s] not valid", tmpMaxResourceFolderSize)); + + maxResourceFolderSize = tmpMaxResourceFolderSize; + logger.info("Set maxResourceFolderSize parameter with value " + maxResourceFolderSize); + } else { + logger.info("Set maxResourceFolderSize parameter with DEFAULT value " + maxResourceFolderSize); + } + } + + private void init() { + allowedFilesNames.add(ExportPathBuilder.DATA_FILENAME); + allowedFilesNames.add(ExportPathBuilder.METADATA_FILENAME); + allowedFilesNames.add(ExportPathBuilder.DOWNLOADED_PLACEHOLDER_FILENAME); + + } + + private void cleanToQuota(Long actualFolderSize, File folder) throws Exception { + logger.debug("IN - cleanToQuota"); + + Comparator creationTimeComparator = new Comparator() { + + @Override + public int compare(File o1, File o2) { + Path pathFile1 = o1.toPath(); + + BasicFileAttributes attrFile1 = null; + try { + attrFile1 = Files.readAttributes(pathFile1, BasicFileAttributes.class); + } catch (IOException e) { + throw new Error("Error while retrieving creation date for file " + o1.getAbsolutePath()); + } + + Path pathFile2 = o2.toPath(); + BasicFileAttributes attrFile2 = null; + try { + attrFile2 = Files.readAttributes(pathFile2, BasicFileAttributes.class); + } catch (IOException e) { + throw new Error("Error while retrieving creation date for file " + o2.getAbsolutePath()); + } + + return attrFile1.creationTime().compareTo(attrFile2.creationTime()); + } + }; + + /* Inside folders are one for every user. We have to bypass them to access to folders eligible for removal */ + File[] files = folder.listFiles(); + List filesInUserFolders = new ArrayList(); + for (File tmpFile1 : files) { + File[] tmpArray = tmpFile1.listFiles(); + for (File tmpFile2 : tmpArray) { + filesInUserFolders.add(tmpFile2); + } + } + + File[] listToArray = filesInUserFolders.toArray(new File[0]); + Arrays.sort(listToArray, creationTimeComparator); + logger.debug("cleanToQuota: Files sorted by creation time"); + + Long desiredFolderSize = Math.round(maxResourceFolderSize * (1 - (cleaningPrecentage / 100))); + Double toRemoveFilesSize = 0.0; + List fileOrFolderToRemove = new ArrayList(); + if (listToArray != null) { + for (File f : listToArray) { + if (actualFolderSize - toRemoveFilesSize > desiredFolderSize) { + logger.debug("cleanToQuota: desiredFolderSize dimension NOT reached"); + + if (isPossibleToRemoveFolderOrFile(f)) { + if (f.isDirectory()) { + toRemoveFilesSize += folderSize(f); + } else { + toRemoveFilesSize += f.length(); + } + fileOrFolderToRemove.add(f.getAbsolutePath()); + } + } else { + logger.debug("cleanToQuota: desiredFolderSize dimension reached"); + break; + } + } + } + + deleteFiles(fileOrFolderToRemove); + + if (actualFolderSize - toRemoveFilesSize > desiredFolderSize) { + String message = String.format("Impossible to reach desired size of " + desiredFolderSize + " Bytes for resource export folder", desiredFolderSize); + logger.info(message); + } + + logger.debug("OUT - cleanToQuota"); + } + + private void deleteFiles(List fileToRemove) { + logger.debug("IN - deleteFiles"); + BasicFileAttributes attrFile1 = null; + Path pathFile = null; + for (String filePath : fileToRemove) { + File f = new File(filePath); + if (f.isDirectory()) { + for (File fileToDelete : f.listFiles()) { + fileToDelete.delete(); + + pathFile = fileToDelete.toPath(); + + try { + attrFile1 = Files.readAttributes(pathFile, BasicFileAttributes.class); + } catch (IOException e) { + throw new Error("Error while retrieving creation date for file " + fileToDelete.getAbsolutePath()); + } + logger.info(String.format("deleteFiles: %s with creation time %s deleted", fileToDelete.getAbsolutePath(), + attrFile1.creationTime().toString())); + } + } + f.delete(); + pathFile = f.toPath(); + + try { + attrFile1 = Files.readAttributes(pathFile, BasicFileAttributes.class); + } catch (IOException e) { + throw new Error("Error while retrieving creation date for file " + f.getAbsolutePath()); + } + logger.info(String.format("deleteFiles: %s with creation time %s deleted", f.getAbsolutePath(), attrFile1.creationTime().toString())); + } + logger.debug("OUT - deleteFiles"); + } + + private boolean isPossibleToRemoveFolderOrFile(File fileOrFolder) { + logger.debug("IN - isPossibleToRemoveFolderOrFile"); + boolean remove = true; + + List foundFilesList = new ArrayList(); + + if (fileOrFolder.isDirectory()) { + for (File fileInFolder : fileOrFolder.listFiles()) { + remove &= Files.isRegularFile(fileInFolder.toPath()); + + String fileInFolderName = fileInFolder.getName(); + if (!allowedFilesNames.contains(fileInFolderName)) { + logger.error(String.format("Found not allowed file [%s]. Folder can't be removed", fileInFolderName)); + return false; + } + foundFilesList.add(fileInFolderName); + } + + boolean requiredFilesFound = foundFilesList.contains(ExportPathBuilder.DATA_FILENAME) + && foundFilesList.contains(ExportPathBuilder.METADATA_FILENAME); + if (requiredFilesFound) { + String message = String.format("[%s] and [%s] files found in folder", ExportPathBuilder.DATA_FILENAME, ExportPathBuilder.METADATA_FILENAME); + logger.debug(message); + } else { + String message = String.format("[%s] and [%s] files NOT found in folder", ExportPathBuilder.DATA_FILENAME, ExportPathBuilder.METADATA_FILENAME); + logger.error(message); + } + + remove &= requiredFilesFound; + + } else { + remove = false; + + String fileInFolderName = fileOrFolder.getName(); + logger.error(String.format("Found file [%s] without temp export folder", fileInFolderName)); + } + + logger.debug( + String.format("%s %s is %s removable", fileOrFolder.isDirectory() ? "Folder" : "File", fileOrFolder.getAbsolutePath(), remove ? "" : "NOT")); + + logger.debug("OUT - isPossibleToRemoveFolderOrFile"); + + return remove; + } + + public long folderSize(File folder) { + logger.debug("IN - folderSize"); + long length = 0; + for (File file : folder.listFiles()) { + if (file.isFile()) { + length += file.length(); + logger.debug(String.format("folderSize: file %s - Length %s", file.getAbsolutePath(), file.length())); + } else { + length += folderSize(file); + } + } + logger.debug("OUT - folderSize"); + return length; + } + + public String getExportTempFolderPath() { + logger.debug("IN"); + String resourcePath = SpagoBIUtilities.getResourcePath(); + return ExportPathBuilder.getInstance().getExportResourcePath(resourcePath).toString(); + } + +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java index dc5400fc459..e6571b5b987 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/service/ManageDataSetsForREST.java @@ -795,7 +795,7 @@ private IDataSet getDataSet(String datasetTypeName, boolean savingDataset, JSONO String tableName = json.optString(DataSetConstants.FLAT_TABLE_NAME); String dataSourceLabel = json.optString(DataSetConstants.DATA_SOURCE_FLAT); jsonDsConfig.put(DataSetConstants.FLAT_TABLE_NAME, tableName); - jsonDsConfig.put(DataSetConstants.DATA_SOURCE, dataSourceLabel); + jsonDsConfig.put(DataSetConstants.DATA_SOURCE_FLAT, dataSourceLabel); dataSet.setTableName(tableName); IDataSource dataSource = DAOFactory.getDataSourceDAO().loadDataSourceByLabel(dataSourceLabel); dataSet.setDataSource(dataSource); diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractEvaluationStrategy.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractEvaluationStrategy.java index feb76a3be1b..90f5fbb3ad4 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractEvaluationStrategy.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractEvaluationStrategy.java @@ -20,11 +20,15 @@ package it.eng.spagobi.tools.dataset.strategy; import java.math.BigDecimal; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.log4j.Logger; @@ -60,19 +64,86 @@ public IDataStore executeQuery(List projections, Filter if (isUnsatisfiedFilter(filter)) { dataStore = new DataStore(dataSet.getMetadata()); } else { - dataStore = execute(projections, filter, groups, sortings, summaryRowProjections, offset, fetchSize, maxRowCount, indexes); + List newProjections = applyTotalsFunctionsToFormulas(projections, filter, maxRowCount); +// List newProjections = projections; + dataStore = execute(newProjections, filter, groups, sortings, summaryRowProjections, offset, fetchSize, maxRowCount, indexes); IMetaData dataStoreToUseMeta = dataStore.getMetaData(); if (!isSummaryRowIncluded() && summaryRowProjections != null && !summaryRowProjections.isEmpty()) { + int i = 0; for (List listProj : summaryRowProjections) { + List replacedSelectionFieldsList = applyTotalsFunctionsToFormulas(listProj, filter, maxRowCount); - IDataStore summaryRowDataStore = executeSummaryRow(listProj, dataStoreToUseMeta, filter, maxRowCount); - appendSummaryRowToPagedDataStore(projections, listProj, dataStore, summaryRowDataStore); + IDataStore summaryRowDataStore = executeSummaryRow(replacedSelectionFieldsList, dataStoreToUseMeta, filter, maxRowCount); + appendSummaryRowToPagedDataStore(newProjections, replacedSelectionFieldsList, dataStore, summaryRowDataStore, i); + i++; } } } return dataStore; } + private List applyTotalsFunctionsToFormulas(List projections, Filter filter, int maxRowCount) { + + List toReturnList = new ArrayList(); + Set totalFunctions = new HashSet(); + for (AbstractSelectionField abstractSelectionField : projections) { + if (abstractSelectionField instanceof DataStoreCalculatedField) { + String formula = ((DataStoreCalculatedField) abstractSelectionField).getFormula(); + if (formula.contains("TOTAL_")) { + + String pattern = "((?:TOTAL_SUM|TOTAL_AVG|TOTAL_MIN|TOTAL_MAX|TOTAL_COUNT)\\()(\\\"[a-zA-Z0-9\\-\\_\\s]*\\\")(\\))"; + + // Create a Pattern object + Pattern r = Pattern.compile(pattern); + + // Now create matcher object. + Matcher m = r.matcher(formula); + while (m.find()) { + totalFunctions.add(m.group(0).replace("TOTAL_", "")); + } + + pattern = "((?:TOTAL_SUM|TOTAL_AVG|TOTAL_MIN|TOTAL_MAX|TOTAL_COUNT)\\()([a-zA-Z0-9\\-\\+\\/\\*\\_\\s\\$\\{\\}\\\"]*)(\\))"; + // Create a Pattern object + r = Pattern.compile(Pattern.quote(pattern)); + + // Now create matcher object. + m = r.matcher(formula); + while (m.find()) { + totalFunctions.add(m.group(0).replace("TOTAL_", "")); + } + } + } + } + + if (!totalFunctions.isEmpty()) { + IDataStore totalsFunctionDataStore = executeTotalsFunctions(totalFunctions, filter, maxRowCount); + + HashMap totalsMap = new HashMap(); + int i = 0; + for (String function : totalFunctions) { + totalsMap.put(function, String.valueOf(totalsFunctionDataStore.getRecordAt(0).getFieldAt(i).getValue())); + i++; + } + + for (AbstractSelectionField abstractSelectionField : projections) { + AbstractSelectionField tmp = abstractSelectionField; + if (tmp instanceof DataStoreCalculatedField) { + String formula = ((DataStoreCalculatedField) tmp).getFormula(); + if (formula.contains("TOTAL_")) { + for (String totalFunction : totalsMap.keySet()) { + formula = formula.replace("TOTAL_" + totalFunction, totalsMap.get(totalFunction)); + } + ((DataStoreCalculatedField) tmp).setFormula(formula); + } + } + toReturnList.add(tmp); + } + } else { + toReturnList = projections; + } + return toReturnList; + } + @Override public IDataStore executeSummaryRowQuery(List summaryRowProjections, Filter filter, int maxRowCount) { return executeSummaryRow(summaryRowProjections, dataSet.getMetadata(), filter, maxRowCount); @@ -81,8 +152,7 @@ public IDataStore executeSummaryRowQuery(List summaryRow protected abstract IDataStore execute(List projections, Filter filter, List groups, List sortings, List> summaryRowProjections, int offset, int fetchSize, int maxRowCount, Set indexes); - protected abstract IDataStore executeSummaryRow(List summaryRowProjections, IMetaData metaData, Filter filter, - int maxRowCount); + protected abstract IDataStore executeSummaryRow(List summaryRowProjections, IMetaData metaData, Filter filter, int maxRowCount); protected boolean isSummaryRowIncluded() { return false; @@ -101,7 +171,7 @@ private boolean isUnsatisfiedFilter(Filter filter) { } private void appendSummaryRowToPagedDataStore(List projections, List summaryRowProjections, - IDataStore pagedDataStore, IDataStore summaryRowDataStore) { + IDataStore pagedDataStore, IDataStore summaryRowDataStore, int row) { IMetaData pagedMetaData = pagedDataStore.getMetaData(); IMetaData summaryRowMetaData = summaryRowDataStore.getMetaData(); @@ -131,7 +201,7 @@ else if (summaryRowProjections.get(i) instanceof DataStoreCalculatedField) } } else { - if (selections instanceof DataStoreCalculatedField) { + if (row == 0 && selections instanceof DataStoreCalculatedField) { DataStoreCalculatedField calcs = (DataStoreCalculatedField) selections; String projectionAlias = calcs.getAlias(); if (summaryRowCalculatedField != null && (summaryRowCalculatedField.getAlias().equals(projectionAlias) @@ -170,4 +240,9 @@ else if (summaryRowProjections.get(i) instanceof DataStoreCalculatedField) } } + + protected IDataStore executeTotalsFunctions(Set summaryRowProjections, Filter filter, int maxRowCount) { + // TODO Auto-generated method stub + return null; + } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractJdbcEvaluationStrategy.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractJdbcEvaluationStrategy.java index d9d74041667..968ae714c6e 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractJdbcEvaluationStrategy.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/AbstractJdbcEvaluationStrategy.java @@ -75,6 +75,20 @@ protected IDataStore executeSummaryRow(List summaryRowPr } } + @Override + protected IDataStore executeTotalsFunctions(Set totalFunctionsProjections, Filter filter, int maxRowCount) { + try { + String[] totalFunctionsProjectionsString = new String[totalFunctionsProjections.size()]; + totalFunctionsProjections.toArray(totalFunctionsProjectionsString); + String totalFunctionsQuery = new SelectQuery(dataSet).select(totalFunctionsProjectionsString).from(getTableName()).where(filter) + .toSql(getDataSource()); + logger.info("Total functions query [ " + totalFunctionsQuery + " ]"); + return getDataSource().executeStatement(totalFunctionsQuery, -1, -1, maxRowCount, false); + } catch (DataBaseException e) { + throw new RuntimeException(e); + } + } + protected abstract String getTableName() throws DataBaseException; protected abstract IDataSource getDataSource(); diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrDiscoveryEvaluationStrategy.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrDiscoveryEvaluationStrategy.java index 6f40e6edbc0..03804550d67 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrDiscoveryEvaluationStrategy.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrDiscoveryEvaluationStrategy.java @@ -20,6 +20,7 @@ package it.eng.spagobi.tools.dataset.strategy; import java.io.IOException; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -42,6 +43,7 @@ import it.eng.spagobi.tools.dataset.common.datastore.IField; import it.eng.spagobi.tools.dataset.common.datastore.IRecord; import it.eng.spagobi.tools.dataset.common.datastore.Record; +import it.eng.spagobi.tools.dataset.common.metadata.FieldMetadata; import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; import it.eng.spagobi.tools.dataset.metasql.query.item.AbstractSelectionField; import it.eng.spagobi.tools.dataset.metasql.query.item.DataStoreCalculatedField; @@ -49,6 +51,7 @@ import it.eng.spagobi.tools.dataset.metasql.query.item.Projection; import it.eng.spagobi.tools.dataset.metasql.query.item.Sorting; import it.eng.spagobi.tools.dataset.solr.ExtendedSolrQuery; +import it.eng.spagobi.tools.dataset.solr.SolrDataStore; import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; class SolrEvaluationStrategy extends AbstractSolrStrategy { @@ -74,6 +77,8 @@ protected IDataStore execute(List projections, Filter fi solrDataSet.setSolrQuery(solrQuery, getFacetsWithAggregation(groups)); dataSet.loadData(offset, fetchSize, maxRowCount); IDataStore dataStore = dataSet.getDataStore(); + + dataStore = checkIfItHasLikeID(dataStore, projections); // Coherence control since LikeSelection uses to add a new "ID" field dataStore.setCacheDate(getDate()); return dataStore; } @@ -138,4 +143,48 @@ private Map getFacetsWithAggregation(List projections) { + + SolrDataStore originalDTS = (SolrDataStore) pagedDataStore; + SolrDataStore datastoresToAdd = new SolrDataStore(originalDTS.getFacets()); + IMetaData pagedMetaData = pagedDataStore.getMetaData(); + Integer idIndex = null; + ArrayList metas = (ArrayList) pagedMetaData.getFieldsMeta(); + boolean hasIdOnMeta = false; + for (int i = 0; i < metas.size(); i++) { + + if (metas.get(i).getName().equalsIgnoreCase("id")) { + idIndex = new Integer(i); + hasIdOnMeta = true; + } + } + + boolean hasId = false; + + for (AbstractSelectionField abstractSelectionField : projections) { + if (abstractSelectionField.getName().equalsIgnoreCase("ID")) { + hasId = true; + } + + } + if (!hasId && hasIdOnMeta) { + + pagedMetaData.deleteFieldMetaDataAt(idIndex); + + datastoresToAdd.setMetaData(pagedMetaData); + + for (int projectionIndex = 0; projectionIndex < pagedDataStore.getRecordsCount(); projectionIndex++) { + Record newRecord = new Record(); + newRecord = (Record) pagedDataStore.getRecordAt(projectionIndex); + newRecord.removeFieldAt(idIndex); + + datastoresToAdd.appendRecord(newRecord); + } + + } else { + datastoresToAdd = originalDTS; + } + return datastoresToAdd; + } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrFacetPivotEvaluationStrategy.java b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrFacetPivotEvaluationStrategy.java index ddb03b19cb6..44cb4328067 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrFacetPivotEvaluationStrategy.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/dataset/strategy/SolrFacetPivotEvaluationStrategy.java @@ -165,7 +165,12 @@ private IDataStore appendCalculatedFieldColumn(AbstractSelectionField abstractSe Object o = scriptManager.runScript(resultingCalculation, "groovy", bindings, imports); String data = (o == null) ? "" : o.toString(); - IField fieldNew = new Field(new BigDecimal(data)); + IField fieldNew = null; + if (data != null && data.isEmpty()) { + fieldNew = new Field(); + } else { + fieldNew = new Field(new BigDecimal(data)); + } newRecord.appendField(fieldNew); datastoresToAdd.appendRecord(newRecord); diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/notification/DatasetNotificationManager.java b/knowage-core/src/main/java/it/eng/spagobi/tools/notification/DatasetNotificationManager.java index 4e67a7e9d4b..4498e7695fd 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/notification/DatasetNotificationManager.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/notification/DatasetNotificationManager.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,57 +11,50 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.notification; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.utilities.StringUtilities; -import it.eng.spagobi.commons.utilities.messages.IMessageBuilder; -import it.eng.spagobi.tools.dataset.bo.IDataSet; - -import java.security.Security; import java.util.List; -import java.util.Properties; import java.util.Set; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import org.apache.log4j.Logger; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; +import it.eng.spagobi.commons.utilities.messages.IMessageBuilder; +import it.eng.spagobi.tools.dataset.bo.IDataSet; + /** * @author Marco Cortella (marco.cortella@eng.it) * */ public class DatasetNotificationManager implements INotificationManager { - + static private Logger logger = Logger.getLogger(DatasetNotificationManager.class); private IMessageBuilder msgBuilder = null; public DatasetNotificationManager(){} - + public DatasetNotificationManager(IMessageBuilder msgBuilder){ this.msgBuilder = msgBuilder; } - + /* (non-Javadoc) * @see it.eng.spagobi.tools.notification.INotificationManager#handleEvent(it.eng.spagobi.tools.notification.AbstractEvent) */ + @Override public void handleEvent(AbstractEvent event) { - + try { if (event instanceof DatasetNotificationEvent){ String eventName = event.getEventName(); @@ -83,7 +76,7 @@ public void handleEvent(AbstractEvent event) { } else if(eventName.equals(EventConstants.DATASET_EVENT_SCOPE_CHANGED)){ notifyDatasetScopeChanged(datasetEvent); } - + } else { logger.debug("Dataset Notification Manager cannot handle the event "+event.getEventName()); } @@ -92,7 +85,8 @@ public void handleEvent(AbstractEvent event) { } } - + + @Override public void handleMultipleEvents(List events){ try { notifyDatasetChanges(events); @@ -101,11 +95,11 @@ public void handleMultipleEvents(List events){ logger.error("Error handling multiple events in DatasetNotification Manager", ex); } } - + private void notifyDatasetChanges(List events) throws Exception{ String information = ""; DatasetNotificationEvent datasetEvent = null; - + for (AbstractEvent event : events){ if (event instanceof DatasetNotificationEvent){ String datasetName = ""; @@ -114,7 +108,7 @@ private void notifyDatasetChanges(List events) throws Exception{ IDataSet dataset = (IDataSet)event.getArgument(); datasetName = dataset.getName(); } - + String eventName = event.getEventName(); information = information + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.1", "messages") + " '" +datasetName+ "' " + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.2", "messages")+ " " ; @@ -137,7 +131,7 @@ private void notifyDatasetChanges(List events) throws Exception{ } else if(eventName.equals(EventConstants.DATASET_EVENT_NAME_CHANGED)){ // information = information +"The dataset "+datasetLabel+" that you are using in a Map, has changed his name. \n"; information = information + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.3.name", "messages"); - + } else if(eventName.equals(EventConstants.DATASET_EVENT_DESCRIPTION_CHANGED)){ // information = information +"The dataset "+datasetLabel+" that you are using in a Map, has changed his description. \n"; information = information + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.3.descr", "messages"); @@ -145,7 +139,7 @@ private void notifyDatasetChanges(List events) throws Exception{ } else if(eventName.equals(EventConstants.DATASET_EVENT_CATEGORY_CHANGED)){ // information = information +"The dataset "+datasetLabel+" that you are using in a Map, has changed his category. \n"; information = information + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.3.cat", "messages"); - + } else if(eventName.equals(EventConstants.DATASET_EVENT_SCOPE_CHANGED)){ // information = information +"The dataset "+datasetLabel+" that you are using in a Map, has changed his scope. \n"; information = information + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.3.scope", "messages"); @@ -153,19 +147,19 @@ private void notifyDatasetChanges(List events) throws Exception{ } } } - + if ((datasetEvent != null) &&(!information.isEmpty() )){ notifyMapAuthorsMail(datasetEvent, msgBuilder.getMessage("SBIDev.DataSet.notify.msg.title"),information ); } } - + private void notifyMapAuthorsMail(DatasetNotificationEvent datasetEvent, String subject, String emailContent) throws Exception{ - + Set emailsAddressOfAuthors = datasetEvent.retrieveEmailAddressesOfMapAuthors(); if (datasetEvent.getArgument() instanceof IDataSet){ if (!emailsAddressOfAuthors.isEmpty()){ String[] recipients = emailsAddressOfAuthors.toArray(new String[0]); - + //send mail try { sendMail(recipients, subject, emailContent); @@ -178,13 +172,13 @@ private void notifyMapAuthorsMail(DatasetNotificationEvent datasetEvent, String } } } - + private void notifyDatasetNameChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); // String subject = "The dataset "+dataset.getName()+" has changed the name"; // String emailContent = "The dataset "+dataset.getName()+" that you are using in a Map, has changed the name"; - + String subject = msgBuilder.getMessage("SBIDev.DataSet.notify.msg.1", "messages") + " '" +dataset.getName()+ "' " + msgBuilder.getMessage("SBIDev.DataSet.notify.msg.3.name", "messages") ; @@ -198,7 +192,7 @@ private void notifyDatasetNameChanged(DatasetNotificationEvent datasetEvent)thro } } } - + private void notifyDatasetDescriptionChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -217,7 +211,7 @@ private void notifyDatasetDescriptionChanged(DatasetNotificationEvent datasetEve } } } - + private void notifyDatasetCategoryChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -236,7 +230,7 @@ private void notifyDatasetCategoryChanged(DatasetNotificationEvent datasetEvent) } } } - + private void notifyDatasetScopeChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -255,7 +249,7 @@ private void notifyDatasetScopeChanged(DatasetNotificationEvent datasetEvent)thr } } } - + private void notifyDatasetMetadataChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -274,8 +268,8 @@ private void notifyDatasetMetadataChanged(DatasetNotificationEvent datasetEvent) } } } - - + + private void notifyDatasetFileChanged(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -295,7 +289,7 @@ private void notifyDatasetFileChanged(DatasetNotificationEvent datasetEvent)thro } } - + private void notifyDatasetDeleted(DatasetNotificationEvent datasetEvent)throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -313,9 +307,9 @@ private void notifyDatasetDeleted(DatasetNotificationEvent datasetEvent)throws E logger.error("Error notifying map authors about dataset deletion with email", e); } } - - } - + + } + private void notifyLicenceChange(DatasetNotificationEvent datasetEvent) throws Exception { if (datasetEvent.getArgument() instanceof IDataSet){ IDataSet dataset = (IDataSet)datasetEvent.getArgument(); @@ -335,97 +329,24 @@ private void notifyLicenceChange(DatasetNotificationEvent datasetEvent) throws E } } - - - private void sendMail(String[] emailAddresses, String subject, String emailContent) throws Exception{ - - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.useSSL"); - logger.debug(smtphost+" "+smtpport+" use SSL: "+smtpssl); - - //Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort=25; - - if( (smtphost==null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if( (smtpport==null) || smtpport.trim().equals("")){ - throw new Exception("Smtp host not configured"); - }else{ - smptPort=Integer.parseInt(smtpport); - } - - String from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.from"); - if( (from==null) || from.trim().equals("")) - from = "spagobi@eng.it"; - String user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.user"); - if( (user==null) || user.trim().equals("")){ - logger.debug("Smtp user not configured"); - user=null; - } - String pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.user.password"); - if( (pass==null) || pass.trim().equals("")){ - logger.debug("Smtp password not configured"); - } - //Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - //Set timeout limit for mail server to respond - props.put("mail.smtp.timeout", "5000"); - props.put("mail.smtp.connectiontimeout", "5000"); - - // open session - Session session=null; - // create autheticator object - Authenticator auth = null; - if (user!=null) { - auth = new SMTPAuthenticator(user, pass); - props.put("mail.smtp.auth", "true"); - //SSL Connection - if (smtpssl.equals("true")){ - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath)) ) { - /* Dynamic configuration of trustedstore for CA - * Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - session = Session.getInstance(props, auth); - logger.info("Session.getInstance(props, auth)"); + private void sendMail(String[] emailAddresses, String subject, String emailContent) throws Exception{ - }else{ - session = Session.getInstance(props); - logger.info("Session.getInstance(props)"); - } + SessionFacade facade = MailSessionBuilder.newInstance() + .usingUserProfile() + .withTimeout(5000) + .withConnectionTimeout(5000) + .build(); // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + InternetAddress[] addressTo = new InternetAddress[emailAddresses.length]; for (int i = 0; i < emailAddresses.length; i++) { addressTo[i] = new InternetAddress(emailAddresses[i]); } - msg.setRecipients(Message.RecipientType.BCC, addressTo); + msg.setRecipients(Message.RecipientType.BCC, addressTo); // Setting the Subject and Content Type msg.setSubject(subject); @@ -437,37 +358,9 @@ private void sendMail(String[] emailAddresses, String subject, String emailConte mp.addBodyPart(mbp1); // add the Multipart to the message msg.setContent(mp); - // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))){ - //USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost,smptPort,user,pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } - else { - //Use normal SMTP - Transport.send(msg); - } - - } - // Private Classes ---------------------------------------------------------------------------- - - private class SMTPAuthenticator extends javax.mail.Authenticator - { - private String username = ""; - private String password = ""; - - public PasswordAuthentication getPasswordAuthentication() - { - return new PasswordAuthentication(username, password); - } - - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } + // send message + facade.sendMessage(msg); } } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/objmetadata/service/DetailObjMetadataModule.java b/knowage-core/src/main/java/it/eng/spagobi/tools/objmetadata/service/DetailObjMetadataModule.java index 1fc2def3b7c..44b5e81795b 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/objmetadata/service/DetailObjMetadataModule.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/objmetadata/service/DetailObjMetadataModule.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,12 +11,21 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.objmetadata.service; +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Vector; + +import org.apache.log4j.Logger; + import it.eng.spago.base.RequestContainer; import it.eng.spago.base.SessionContainer; import it.eng.spago.base.SourceBean; @@ -35,17 +44,8 @@ import it.eng.spagobi.tools.objmetadata.bo.ObjMetadata; import it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Vector; - -import org.apache.log4j.Logger; - /** - * This class implements a module which handles data source management. + * This class implements a module which handles data source management. */ public class DetailObjMetadataModule extends AbstractModule { static private Logger logger = Logger.getLogger(DetailObjMetadataModule.class); @@ -54,25 +54,29 @@ public class DetailObjMetadataModule extends AbstractModule { public static final String OBJMETA_DATA_TYPE = "dataTypes"; private String modalita = ""; - - /* (non-Javadoc) + + /* + * (non-Javadoc) + * * @see it.eng.spago.dispatching.module.AbstractModule#init(it.eng.spago.base.SourceBean) */ + @Override public void init(SourceBean config) { } /** * Reads the operation asked by the user and calls the insertion, updation or deletion methods. - * - * @param request The Source Bean containing all request parameters + * + * @param request The Source Bean containing all request parameters * @param response The Source Bean containing all response parameters - * + * * @throws exception If an exception occurs * @throws Exception the exception */ + @Override public void service(SourceBean request, SourceBean response) throws Exception { String message = (String) request.getAttribute("MESSAGEDET"); - logger.debug("begin of detail Data Source service with message =" +message); + logger.debug("begin of detail Data Source service with message =" + message); EMFErrorHandler errorHandler = getErrorHandler(); try { if (message == null) { @@ -101,25 +105,20 @@ public void service(SourceBean request, SourceBean response) throws Exception { return; } } - - - + /** - * Gets the detail of a obj metadata choosed by the user from the - * obj metadata list. It reaches the key from the request and asks to the DB all detail + * Gets the detail of a obj metadata choosed by the user from the obj metadata list. It reaches the key from the request and asks to the DB all detail * objmetadata information, by calling the method loadObjMetadataByID. - * - * @param key The choosed metadata id key + * + * @param key The choosed metadata id key * @param response The response Source Bean * @throws EMFUserError If an exception occurs - */ - private void getObjMetadata(SourceBean request, SourceBean response) throws EMFUserError { - try { - ObjMetadata meta = DAOFactory.getObjMetadataDAO().loadObjMetaDataByID(new Integer((String)request.getAttribute("ID"))); + */ + private void getObjMetadata(SourceBean request, SourceBean response) throws EMFUserError { + try { + ObjMetadata meta = DAOFactory.getObjMetadataDAO().loadObjMetaDataByID(new Integer((String) request.getAttribute("ID"))); this.modalita = SpagoBIConstants.DETAIL_MOD; - if (request.getAttribute("SUBMESSAGEDET") != null && - ((String)request.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVEBACK)) - { + if (request.getAttribute("SUBMESSAGEDET") != null && ((String) request.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVEBACK)) { response.setAttribute("loopback", "true"); return; } @@ -129,41 +128,40 @@ private void getObjMetadata(SourceBean request, SourceBean response) throws EMFU response.setAttribute("modality", modalita); response.setAttribute("metaObj", meta); } catch (Exception ex) { - logger.error("Cannot fill response container" + ex.getLocalizedMessage()); + logger.error("Cannot fill response container" + ex.getLocalizedMessage()); HashMap params = new HashMap(); params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); throw new EMFUserError(EMFErrorSeverity.ERROR, 13003, new Vector(), params); } - + } - /** - * Inserts/Modifies the detail of a object metadta according to the user request. - * When a metadata is modified, the modifyObjMetadata method is called; when a new - * metadata is added, the insertObjMetadatamethod is called. These two cases are - * differentiated by the mod String input value . - * - * @param request The request information contained in a SourceBean Object - * @param mod A request string used to differentiate insert/modify operations - * @param response The response SourceBean - * @throws EMFUserError If an exception occurs + + /** + * Inserts/Modifies the detail of a object metadta according to the user request. When a metadata is modified, the modifyObjMetadata method is + * called; when a new metadata is added, the insertObjMetadatamethod is called. These two cases are differentiated by the mod + * String input value . + * + * @param request The request information contained in a SourceBean Object + * @param mod A request string used to differentiate insert/modify operations + * @param response The response SourceBean + * @throws EMFUserError If an exception occurs * @throws SourceBeanException If a SourceBean exception occurs */ - private void modifyObjMetadata(SourceBean serviceRequest, String mod, SourceBean serviceResponse) - throws EMFUserError, SourceBeanException { - + private void modifyObjMetadata(SourceBean serviceRequest, String mod, SourceBean serviceResponse) throws EMFUserError, SourceBeanException { + try { RequestContainer reqCont = getRequestContainer(); SessionContainer sessCont = reqCont.getSessionContainer(); SessionContainer permSess = sessCont.getPermanentContainer(); - IEngUserProfile profile = (IEngUserProfile)permSess.getAttribute(IEngUserProfile.ENG_USER_PROFILE); - - IObjMetadataDAO dao=DAOFactory.getObjMetadataDAO(); + IEngUserProfile profile = (IEngUserProfile) permSess.getAttribute(IEngUserProfile.ENG_USER_PROFILE); + + IObjMetadataDAO dao = DAOFactory.getObjMetadataDAO(); dao.setUserProfile(profile); - + ObjMetadata metaNew = recoverObjMetadataDetails(serviceRequest); - + EMFErrorHandler errorHandler = getErrorHandler(); - + // if there are some validation errors into the errorHandler does not write into DB Collection errors = errorHandler.getErrors(); if (errors != null && errors.size() > 0) { @@ -177,113 +175,103 @@ private void modifyObjMetadata(SourceBean serviceRequest, String mod, SourceBean } } } - - if (mod.equalsIgnoreCase(SpagoBIConstants.DETAIL_INS)) { - //if a ds with the same label not exists on db ok else error - if (dao.loadObjMetadataByLabel(metaNew.getLabel()) != null){ + + if (mod.equalsIgnoreCase(SpagoBIConstants.DETAIL_INS)) { + // if a ds with the same label not exists on db ok else error + List metadataWithSameLabel = dao.loadAllObjMetadataByLabelAndCase(metaNew.getLabel(), false); + if (metadataWithSameLabel != null && metadataWithSameLabel.size() > 0) { HashMap params = new HashMap(); params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); - EMFUserError error = new EMFUserError(EMFErrorSeverity.ERROR, 13004, new Vector(), params ); + EMFUserError error = new EMFUserError(EMFErrorSeverity.ERROR, 13004, new Vector(), params); getErrorHandler().addError(error); return; - } + } dao.insertObjMetadata(metaNew); - + ObjMetadata tmpMeta = dao.loadObjMetadataByLabel(metaNew.getLabel()); metaNew.setObjMetaId(tmpMeta.getObjMetaId()); - mod = SpagoBIConstants.DETAIL_MOD; - } else { - //update metadata - dao.modifyObjMetadata(metaNew); - } + mod = SpagoBIConstants.DETAIL_MOD; + } else { + // update metadata + dao.modifyObjMetadata(metaNew); + } IDomainDAO domaindao = DAOFactory.getDomainDAO(); List dataTypes = domaindao.loadListDomainsByType("OBJMETA_DATA_TYPE"); serviceResponse.setAttribute(OBJMETA_DATA_TYPE, dataTypes); - - if (serviceRequest.getAttribute("SUBMESSAGEDET") != null && - ((String)serviceRequest.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVE)) { + + if (serviceRequest.getAttribute("SUBMESSAGEDET") != null && ((String) serviceRequest.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVE)) { serviceResponse.setAttribute("modality", mod); - serviceResponse.setAttribute("metaObj", metaNew); + serviceResponse.setAttribute("metaObj", metaNew); + return; + } else if (serviceRequest.getAttribute("SUBMESSAGEDET") != null + && ((String) serviceRequest.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVEBACK)) { + serviceResponse.setAttribute("loopback", "true"); return; } - else if (serviceRequest.getAttribute("SUBMESSAGEDET") != null && - ((String)serviceRequest.getAttribute("SUBMESSAGEDET")).equalsIgnoreCase(MOD_SAVEBACK)){ - serviceResponse.setAttribute("loopback", "true"); - return; - } - } catch (EMFUserError e){ + } catch (EMFUserError e) { logger.error("Cannot fill response container" + e.getLocalizedMessage()); HashMap params = new HashMap(); params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); throw new EMFUserError(EMFErrorSeverity.ERROR, 13005, new Vector(), params); - + } - - catch (Exception ex) { - logger.error("Cannot fill response container" , ex); + + catch (Exception ex) { + logger.error("Cannot fill response container", ex); throw new EMFUserError(EMFErrorSeverity.ERROR, 100); - } + } } /** * Deletes an obj metadata choosed by user from the metadata list. - * - * @param request The request SourceBean - * @param mod A request string used to differentiate delete operation - * @param response The response SourceBean - * @throws EMFUserError If an Exception occurs + * + * @param request The request SourceBean + * @param mod A request string used to differentiate delete operation + * @param response The response SourceBean + * @throws EMFUserError If an Exception occurs * @throws SourceBeanException If a SourceBean Exception occurs */ - private void deleteObjMetadata(SourceBean request, String mod, SourceBean response) - throws EMFUserError, SourceBeanException { - + private void deleteObjMetadata(SourceBean request, String mod, SourceBean response) throws EMFUserError, SourceBeanException { + try { String id = (String) request.getAttribute("ID"); // if the metadata is associated with any BIObjects or BISuobjets, creates an error - /*boolean bObjects = DAOFactory.getObjMetadataDAO().hasBIObjAssociated(id); - boolean bSubobjects = DAOFactory.getObjMetadataDAO().hasSubObjAssociated(id); - if (bObjects || bSubobjects){ - HashMap params = new HashMap(); - params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); - EMFUserError error = new EMFUserError(EMFErrorSeverity.ERROR, 13007, new Vector(), params ); - getErrorHandler().addError(error); - return; - }*/ - - //delete the metadata + /* + * boolean bObjects = DAOFactory.getObjMetadataDAO().hasBIObjAssociated(id); boolean bSubobjects = + * DAOFactory.getObjMetadataDAO().hasSubObjAssociated(id); if (bObjects || bSubobjects){ HashMap params = new HashMap(); + * params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); EMFUserError error = new EMFUserError(EMFErrorSeverity.ERROR, 13007, new + * Vector(), params ); getErrorHandler().addError(error); return; } + */ + + // delete the metadata ObjMetadata meta = DAOFactory.getObjMetadataDAO().loadObjMetaDataByID(new Integer(id)); DAOFactory.getObjMetadataDAO().eraseObjMetadata(meta); - } - catch (EMFUserError e){ - logger.error("Cannot fill response container" + e.getLocalizedMessage()); - HashMap params = new HashMap(); - params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); - throw new EMFUserError(EMFErrorSeverity.ERROR, 13006, new Vector(), params); - - } - catch (Exception ex) { - ex.printStackTrace(); - logger.error("Cannot fill response container" ,ex); + } catch (EMFUserError e) { + logger.error("Cannot fill response container" + e.getLocalizedMessage()); + HashMap params = new HashMap(); + params.put(AdmintoolsConstants.PAGE, ListObjMetadataModule.MODULE_PAGE); + throw new EMFUserError(EMFErrorSeverity.ERROR, 13006, new Vector(), params); + + } catch (Exception ex) { + ex.printStackTrace(); + logger.error("Cannot fill response container", ex); throw new EMFUserError(EMFErrorSeverity.ERROR, 100); - } - response.setAttribute("loopback", "true"); + } + response.setAttribute("loopback", "true"); } - - /** - * Instantiates a new objmetadata object when a new metadata insertion is required, in order - * to prepare the page for the insertion. - * + * Instantiates a new objmetadata object when a new metadata insertion is required, in order to prepare the page for the insertion. + * * @param response The response SourceBean * @throws EMFUserError If an Exception occurred */ private void newObjMetadata(SourceBean response) throws EMFUserError { - + try { - + ObjMetadata meta = null; this.modalita = SpagoBIConstants.DETAIL_INS; response.setAttribute("modality", modalita); @@ -295,38 +283,36 @@ private void newObjMetadata(SourceBean response) throws EMFUserError { meta.setName(""); meta.setCreationDate(null); response.setAttribute("metaObj", meta); - + IDomainDAO domaindao = DAOFactory.getDomainDAO(); List dataTypes = domaindao.loadListDomainsByType("OBJMETA_DATA_TYPE"); response.setAttribute(OBJMETA_DATA_TYPE, dataTypes); - + } catch (Exception ex) { - logger.error("Cannot prepare page for the insertion" , ex); + logger.error("Cannot prepare page for the insertion", ex); throw new EMFUserError(EMFErrorSeverity.ERROR, 100); } - + } + private ObjMetadata recoverObjMetadataDetails(SourceBean serviceRequest) throws EMFUserError, SourceBeanException, IOException { + ObjMetadata meta = new ObjMetadata(); - private ObjMetadata recoverObjMetadataDetails (SourceBean serviceRequest) throws EMFUserError, SourceBeanException, IOException { - ObjMetadata meta = new ObjMetadata(); - - String idStr = (String)serviceRequest.getAttribute("ID"); + String idStr = (String) serviceRequest.getAttribute("ID"); Integer id = new Integer(idStr); - String description = (String)serviceRequest.getAttribute("DESCR"); - String label = (String)serviceRequest.getAttribute("LABEL"); - String name = (String)serviceRequest.getAttribute("NAME"); - String dataType = (String)serviceRequest.getAttribute("DATA_TYPE"); - //String creationDate = (String)serviceRequest.getAttribute("USER"); - + String description = (String) serviceRequest.getAttribute("DESCR"); + String label = (String) serviceRequest.getAttribute("LABEL"); + String name = (String) serviceRequest.getAttribute("NAME"); + String dataType = (String) serviceRequest.getAttribute("DATA_TYPE"); + // String creationDate = (String)serviceRequest.getAttribute("USER"); + meta.setObjMetaId(id.intValue()); meta.setDescription(description); meta.setLabel(label); meta.setDataType(Integer.valueOf(dataType)); meta.setName(name); - //meta.setCreationDate(creationDate); - - + // meta.setCreationDate(creationDate); + return meta; } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/DistributionListDocumentDispatchChannel.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/DistributionListDocumentDispatchChannel.java index aef808834e6..a4a9cf45d90 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/DistributionListDocumentDispatchChannel.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/DistributionListDocumentDispatchChannel.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -21,59 +21,34 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.Security; -import java.sql.Timestamp; import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; -import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import it.eng.spago.error.EMFUserError; +import org.apache.log4j.Logger; +import org.quartz.JobExecutionContext; + +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; import it.eng.spago.security.IEngUserProfile; import it.eng.spagobi.analiticalmodel.document.bo.BIObject; -import it.eng.spagobi.analiticalmodel.document.bo.ObjTemplate; -import it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO; -import it.eng.spagobi.analiticalmodel.functionalitytree.bo.LowFunctionality; -import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.bo.Domain; import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IDomainDAO; import it.eng.spagobi.commons.utilities.GeneralUtilities; import it.eng.spagobi.commons.utilities.ObjectsAccessVerifier; -import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.commons.utilities.messages.IMessageBuilder; import it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory; -import it.eng.spagobi.engines.config.bo.Engine; -import it.eng.spagobi.engines.config.dao.IEngineDAO; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.common.datastore.IField; -import it.eng.spagobi.tools.dataset.common.datastore.IRecord; import it.eng.spagobi.tools.distributionlist.bo.DistributionList; import it.eng.spagobi.tools.distributionlist.bo.Email; -import it.eng.spagobi.tools.massiveExport.services.StartMassiveScheduleAction; import it.eng.spagobi.tools.scheduler.to.DispatchContext; -import org.apache.commons.validator.GenericValidator; -import org.apache.log4j.Logger; -import org.quartz.JobExecutionContext; - /** * @author Andrea Gioia (andrea.gioia@eng.it) * @@ -81,79 +56,50 @@ public class DistributionListDocumentDispatchChannel implements IDocumentDispatchChannel { private DispatchContext dispatchContext; - + // logger component - private static Logger logger = Logger.getLogger(DistributionListDocumentDispatchChannel.class); - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - + private static Logger logger = Logger.getLogger(DistributionListDocumentDispatchChannel.class); + public DistributionListDocumentDispatchChannel(DispatchContext dispatchContext) { this.dispatchContext = dispatchContext; } - + + @Override public void setDispatchContext(DispatchContext dispatchContext) { this.dispatchContext = dispatchContext; } + @Override public void close() { - + } - + + @Override public boolean canDispatch(BIObject document) { return true; } - + + @Override public boolean dispatch(BIObject document, byte[] executionOutput) { - + String contentType; String fileExtension; String nameSuffix; JobExecutionContext jobExecutionContext; - + logger.debug("IN"); - + try{ - + contentType = dispatchContext.getContentType(); fileExtension = dispatchContext.getFileExtension(); nameSuffix = dispatchContext.getNameSuffix(); jobExecutionContext = dispatchContext.getJobExecutionContext(); - - //Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.useSSL"); - logger.debug(smtphost+" "+smtpport+" use SSL: "+smtpssl); - - - if( (smtphost==null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - String from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.from"); - if( (from==null) || from.trim().equals("")) - from = "spagobi.scheduler@eng.it"; - - int smptPort=25; - - if( (smtpport==null) || smtpport.trim().equals("")){ - throw new Exception("Smtp host not configured"); - }else{ - smptPort=Integer.parseInt(smtpport); - } - - String user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.user"); - String pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.password"); - - /* - if( (user==null) || user.trim().equals("")) - throw new Exception("Smtp user not configured"); - - if( (pass==null) || pass.trim().equals("")) - throw new Exception("Smtp password not configured"); - */ - + + SessionFacade facade = MailSessionBuilder.newInstance() + .usingSchedulerProfile() + .build(); + String mailTos = ""; List dlIds = dispatchContext.getDlIds(); Iterator it = dlIds.iterator(); @@ -169,8 +115,8 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { Email e = (Email) j.next(); String email = e.getEmail(); String userTemp = e.getUserId(); - IEngUserProfile userProfile = GeneralUtilities.createNewUserProfile(userTemp); - if(ObjectsAccessVerifier.canSee(document, userProfile)) { + IEngUserProfile userProfile = GeneralUtilities.createNewUserProfile(userTemp); + if(ObjectsAccessVerifier.canSee(document, userProfile)) { if (j.hasNext()) {mailTos = mailTos+email+",";} else {mailTos = mailTos+email;} } @@ -179,55 +125,15 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { } - if( (mailTos==null) || mailTos.trim().equals("")) { + if( (mailTos==null) || mailTos.trim().equals("")) { throw new Exception("No recipient address found"); } String[] recipients = mailTos.split(","); - //Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - - Session session = null; - - if(StringUtilities.isEmpty(user) || StringUtilities.isEmpty(pass)) { - props.put("mail.smtp.auth", "false"); - session = Session.getInstance(props); - logger.debug("Connecting to mail server without authentication"); - } else { - props.put("mail.smtp.auth", "true"); - Authenticator auth = new SMTPAuthenticator(user, pass); - //SSL Connection - if (smtpssl.equals("true")){ - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - //props.put("mail.smtp.debug", "true"); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath)) ) { - /* Dynamic configuration of trustedstore for CA - * Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - //System.setProperty("java.security.debug","certpath"); - //System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - //System.setProperty("java.security.debug","certpath"); - //System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - session = Session.getInstance(props, auth); - logger.debug("Connecting to mail server with authentication"); - } - + // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { addressTo[i] = new InternetAddress(recipients[i]); @@ -252,19 +158,10 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { mp.addBodyPart(mbp2); // add the Multipart to the message msg.setContent(mp); + // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))){ - //USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost,smptPort,user,pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } - else { - //Use normal SMTP - Transport.send(msg); - } - + facade.sendMessage(msg); + if(jobExecutionContext.getNextFireTime()== null){ String triggername = jobExecutionContext.getTrigger().getName(); dlIds = dispatchContext.getDlIds(); @@ -281,48 +178,33 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { }finally{ logger.debug("OUT"); } - - return true; - } - - - - private class SMTPAuthenticator extends javax.mail.Authenticator - { - private String username = ""; - private String password = ""; - - public PasswordAuthentication getPasswordAuthentication() - { - return new PasswordAuthentication(username, password); - } - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } + return true; } - private class SchedulerDataSource implements DataSource { byte[] content = null; String name = null; String contentType = null; + @Override public String getContentType() { return contentType; } + @Override public InputStream getInputStream() throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(content); return bais; } + @Override public String getName() { return name; } + @Override public OutputStream getOutputStream() throws IOException { return null; } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/MailDocumentDispatchChannel.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/MailDocumentDispatchChannel.java index 6a230e97cae..fd6a25a2928 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/MailDocumentDispatchChannel.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/MailDocumentDispatchChannel.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,62 +11,57 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.scheduler.dispatcher; -import it.eng.spago.security.IEngUserProfile; -import it.eng.spagobi.analiticalmodel.document.bo.BIObject; -import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.utilities.StringUtilities; -import it.eng.spagobi.tools.dataset.bo.IDataSet; -import it.eng.spagobi.tools.dataset.common.behaviour.UserProfileUtils; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.common.datastore.IField; -import it.eng.spagobi.tools.dataset.common.datastore.IRecord; -import it.eng.spagobi.tools.scheduler.to.DispatchContext; -import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.Security; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.activation.DataHandler; import javax.activation.DataSource; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.util.ByteArrayDataSource; import org.apache.commons.validator.GenericValidator; import org.apache.log4j.Logger; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.utilities.StringUtilities; +import it.eng.spagobi.tools.dataset.bo.IDataSet; +import it.eng.spagobi.tools.dataset.common.behaviour.UserProfileUtils; +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; +import it.eng.spagobi.tools.dataset.common.datastore.IField; +import it.eng.spagobi.tools.dataset.common.datastore.IRecord; +import it.eng.spagobi.tools.scheduler.to.DispatchContext; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + /** * @author Andrea Gioia (andrea.gioia@eng.it) - * + * */ public class MailDocumentDispatchChannel implements IDocumentDispatchChannel { @@ -74,8 +69,6 @@ public class MailDocumentDispatchChannel implements IDocumentDispatchChannel { // logger component private static Logger logger = Logger.getLogger(MailDocumentDispatchChannel.class); - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; public MailDocumentDispatchChannel(DispatchContext dispatchContext) { this.dispatchContext = dispatchContext; @@ -95,18 +88,22 @@ public MailDocumentDispatchChannel(DispatchContext dispatchContext) { } } + @Override public void setDispatchContext(DispatchContext dispatchContext) { this.dispatchContext = dispatchContext; } + @Override public void close() { } + @Override public boolean canDispatch(BIObject document) { return canDispatch(dispatchContext, document, dispatchContext.getEmailDispatchDataStore()); } + @Override public boolean dispatch(BIObject document, byte[] executionOutput) { Map parametersMap; String contentType; @@ -132,39 +129,9 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { : document.getName(); reportNameInSubject = dispatchContext.isReportNameInSubject(); - String smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtphost"); - String smtpport = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtpport"); - String smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.useSSL"); - logger.debug(smtphost + " " + smtpport + " use SSL: " + smtpssl); - - // Custom Trusted Store Certificate Options - String trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - String trustedStorePassword = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.password"); - - int smptPort = 25; - - if ((smtphost == null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if ((smtpport == null) || smtpport.trim().equals("")) { - throw new Exception("Smtp host not configured"); - } else { - smptPort = Integer.parseInt(smtpport); - } - - String from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.from"); - if ((from == null) || from.trim().equals("")) - from = "spagobi.scheduler@eng.it"; - String user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.user"); - if ((user == null) || user.trim().equals("")) { - logger.debug("Smtp user not configured"); - user = null; - } - // throw new Exception("Smtp user not configured"); - String pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.password"); - if ((pass == null) || pass.trim().equals("")) { - logger.debug("Smtp password not configured"); - } - // throw new Exception("Smtp password not configured"); + SessionFacade facade = MailSessionBuilder.newInstance() + .usingSchedulerProfile() + .build(); String mailSubj = dispatchContext.getMailSubj(); mailSubj = StringUtilities.substituteParametersInString(mailSubj, parametersMap, null, false); @@ -177,58 +144,8 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { return false; } - // Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.port", Integer.toString(smptPort)); - - // open session - Session session = null; - - // create autheticator object - Authenticator auth = null; - if (user != null) { - auth = new SMTPAuthenticator(user, pass); - props.put("mail.smtp.auth", "true"); - // SSL Connection - if (smtpssl.equals("true")) { - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - // props.put("mail.smtp.debug", "true"); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smptPort)); - if ((!StringUtilities.isEmpty(trustedStorePath))) { - /* - * Dynamic configuration of trustedstore for CA Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - // System.setProperty("java.security.debug","certpath"); - // System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - // session = Session.getDefaultInstance(props, auth); - session = Session.getInstance(props, auth); - // session.setDebug(true); - // session.setDebugOut(null); - logger.info("Session.getInstance(props, auth)"); - - } else { - // session = Session.getDefaultInstance(props); - session = Session.getInstance(props); - logger.info("Session.getInstance(props)"); - } - // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { addressTo[i] = new InternetAddress(recipients[i]); @@ -269,16 +186,7 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { // add the Multipart to the message msg.setContent(mp); // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))) { - // USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost, smptPort, user, pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } else { - // Use normal SMTP - Transport.send(msg); - } + facade.sendMessage(msg); logger.info("Mail sent for document with label " + document.getLabel()); } catch (Exception e) { @@ -529,40 +437,29 @@ private static List findRecipientsFromDataSet(DispatchContext info, BIOb return recipients; } - private class SMTPAuthenticator extends javax.mail.Authenticator { - private String username = ""; - private String password = ""; - - @Override - public PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(username, password); - } - - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } - } - private class SchedulerDataSource implements DataSource { byte[] content = null; String name = null; String contentType = null; + @Override public String getContentType() { return contentType; } + @Override public InputStream getInputStream() throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(content); return bais; } + @Override public String getName() { return name; } + @Override public OutputStream getOutputStream() throws IOException { return null; } diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/UniqueMailDocumentDispatchChannel.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/UniqueMailDocumentDispatchChannel.java index df5f135d799..7cc69ef4c90 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/UniqueMailDocumentDispatchChannel.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/dispatcher/UniqueMailDocumentDispatchChannel.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,26 +11,12 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.scheduler.dispatcher; -import it.eng.spago.security.IEngUserProfile; -import it.eng.spagobi.analiticalmodel.document.bo.BIObject; -import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.utilities.StringUtilities; -import it.eng.spagobi.tools.dataset.bo.IDataSet; -import it.eng.spagobi.tools.dataset.common.behaviour.UserProfileUtils; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.common.datastore.IField; -import it.eng.spagobi.tools.dataset.common.datastore.IRecord; -import it.eng.spagobi.tools.scheduler.to.DispatchContext; -import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; - import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -39,34 +25,43 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.security.Security; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import javax.activation.DataHandler; import javax.activation.DataSource; -import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.Multipart; import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.util.ByteArrayDataSource; import org.apache.commons.validator.GenericValidator; import org.apache.log4j.Logger; +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.utilities.StringUtilities; +import it.eng.spagobi.tools.dataset.bo.IDataSet; +import it.eng.spagobi.tools.dataset.common.behaviour.UserProfileUtils; +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; +import it.eng.spagobi.tools.dataset.common.datastore.IField; +import it.eng.spagobi.tools.dataset.common.datastore.IRecord; +import it.eng.spagobi.tools.scheduler.to.DispatchContext; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + /** * @author Giulio Gavardi * @@ -76,7 +71,7 @@ public class UniqueMailDocumentDispatchChannel implements IDocumentDispatchChann private DispatchContext dispatchContext; // logger component - private static Logger logger = Logger.getLogger(UniqueMailDocumentDispatchChannel.class); + private static Logger logger = Logger.getLogger(UniqueMailDocumentDispatchChannel.class); // COnfigurations stored in mailOptions Map @@ -95,8 +90,8 @@ public class UniqueMailDocumentDispatchChannel implements IDocumentDispatchChann public static final String DOCUMENT_STATE_CODE = "DOCUMENT_STATE_CODE"; public static final String PARAMETERS_MAP = "PARAMETERS_MAP"; public static final String REPORT_NAME_IN_SUBJECT = "REPORT_NAME_IN_SUBJECT"; - public static final String DOCUMENT_LABELS = "DOCUMENT_LABELS"; - public static final String IS_ZIP_DOCUMENT = "IS_ZIP_DOCUMENT"; + public static final String DOCUMENT_LABELS = "DOCUMENT_LABELS"; + public static final String IS_ZIP_DOCUMENT = "IS_ZIP_DOCUMENT"; @@ -122,31 +117,35 @@ public UniqueMailDocumentDispatchChannel(DispatchContext dispatchContext) { } } + @Override public void setDispatchContext(DispatchContext dispatchContext) { this.dispatchContext = dispatchContext; } + @Override public void close() { } + @Override public boolean canDispatch(BIObject document) { return canDispatch(dispatchContext, document, dispatchContext.getEmailDispatchDataStore() ); } - + /** * dispatch in this case does not send mail, but store files in temporar folder */ - + + @Override public boolean dispatch(BIObject document, byte[] executionOutput) { - String fileExtension; + String fileExtension; String nameSuffix; String containedFileName; logger.debug("IN"); try{ - fileExtension = dispatchContext.getFileExtension(); + fileExtension = dispatchContext.getFileExtension(); nameSuffix = dispatchContext.getNameSuffix(); containedFileName = dispatchContext.getContainedFileName() != null && !dispatchContext.getContainedFileName().equals("")? dispatchContext.getContainedFileName() : document.getName(); @@ -158,7 +157,7 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { File folder = new File(tempFolderPath); if(!folder.exists()){ - logger.debug("Temporary Folder not retrieved: "+folder.getAbsolutePath()); + logger.debug("Temporary Folder not retrieved: "+folder.getAbsolutePath()); throw new Exception("Temporary Folder not retrieved: "+folder.getAbsolutePath()); } @@ -170,7 +169,7 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { logger.debug("File to store in temporary folder: "+fileToCreate); String pathToCreate = folder.getAbsolutePath()+File.separator+fileToCreate; - FileOutputStream fileOuputStream = new FileOutputStream(pathToCreate); + FileOutputStream fileOuputStream = new FileOutputStream(pathToCreate); fileOuputStream.write(executionOutput); fileOuputStream.close(); @@ -188,7 +187,7 @@ public boolean dispatch(BIObject document, byte[] executionOutput) { /** AFter all files are stored in temporary tabe takes them and sens as zip or as separate attachments - * + * * @param mailOptions * @return */ @@ -197,9 +196,6 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe logger.debug("IN"); try{ - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - String tempFolderPath = (String)mailOptions.get(TEMP_FOLDER_PATH); File tempFolder = new File(tempFolderPath); @@ -209,52 +205,9 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe return false; } - String smtphost = null; - String pass = null; - String smtpssl = null; - String trustedStorePath = null; - String user = null; - String from = null; - int smtpPort = 25; - - try{ - - smtphost = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtphost"); - String smtpportS = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.smtpport"); - smtpssl = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.useSSL"); - logger.debug(smtphost+" "+smtpportS+" use SSL: "+smtpssl); - //Custom Trusted Store Certificate Options - trustedStorePath = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.trustedStore.file"); - - - if( (smtphost==null) || smtphost.trim().equals("")) - throw new Exception("Smtp host not configured"); - if( (smtpportS==null) || smtpportS.trim().equals("")){ - throw new Exception("Smtp host not configured"); - }else{ - smtpPort=Integer.parseInt(smtpportS); - } - - from = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.from"); - if( (from==null) || from.trim().equals("")) - from = "spagobi.scheduler@eng.it"; - user = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.user"); - if( (user==null) || user.trim().equals("")){ - logger.debug("Smtp user not configured"); - user=null; - } - // throw new Exception("Smtp user not configured"); - pass = SingletonConfig.getInstance().getConfigValue("MAIL.PROFILES.scheduler.password"); - if( (pass==null) || pass.trim().equals("")){ - logger.debug("Smtp password not configured"); - } - // throw new Exception("Smtp password not configured"); - } - catch(Exception e){ - logger.error("Some E-mail configuration not set in table sbi_config: check you have all settings.", e); - throw new Exception("Some E-mail configuration not set in table sbi_config: check you have all settings."); - } - + SessionFacade facade = MailSessionBuilder.newInstance() + .usingSchedulerProfile() + .build(); String mailSubj = mailOptions.get(MAIL_SUBJECT) != null ? (String)mailOptions.get(MAIL_SUBJECT) : null; Map parametersMap = mailOptions.get(PARAMETERS_MAP) != null ? (Map)mailOptions.get(PARAMETERS_MAP) : null; @@ -263,60 +216,9 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe String mailTxt = mailOptions.get(MAIL_TXT) != null ? (String)mailOptions.get(MAIL_TXT) : null; String[] recipients = mailOptions.get(RECIPIENTS) != null ? (String[])mailOptions.get(RECIPIENTS) : null; - - //Set the host smtp address - Properties props = new Properties(); - props.put("mail.smtp.host", smtphost); - props.put("mail.smtp.p ort", Integer.toString(smtpPort)); - - // open session - Session session=null; - - // create autheticator object - Authenticator auth = null; - if (user!=null) { - auth = new SMTPAuthenticator(user, pass); - props.put("mail.smtp.auth", "true"); - //SSL Connection - if (smtpssl.equals("true")){ - Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); - //props.put("mail.smtp.debug", "true"); - props.put("mail.smtps.auth", "true"); - props.put("mail.smtps.socketFactory.port", Integer.toString(smtpPort)); - if ((!StringUtilities.isEmpty(trustedStorePath)) ) { - /* Dynamic configuration of trustedstore for CA - * Using Custom SSLSocketFactory to inject certificates directly from specified files - */ - //System.setProperty("java.security.debug","certpath"); - //System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); - - } else { - //System.setProperty("java.security.debug","certpath"); - //System.setProperty("javax.net.debug","ssl "); - props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); - } - props.put("mail.smtp.socketFactory.fallback", "false"); - } - - //session = Session.getDefaultInstance(props, auth); - session = Session.getInstance(props, auth); - //session.setDebug(true); - //session.setDebugOut(null); - logger.info("Session.getInstance(props, auth)"); - - }else{ - //session = Session.getDefaultInstance(props); - session = Session.getInstance(props); - logger.info("Session.getInstance(props)"); - } - - // create a message - Message msg = new MimeMessage(session); - // set the from and to address - InternetAddress addressFrom = new InternetAddress(from); - msg.setFrom(addressFrom); + Message msg = facade.createNewMimeMessage(); + InternetAddress[] addressTo = new InternetAddress[recipients.length]; for (int i = 0; i < recipients.length; i++) { addressTo[i] = new InternetAddress(recipients[i]); @@ -352,12 +254,12 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe mp.addBodyPart(mbp1); - if(isZipDocument){ + if(isZipDocument){ logger.debug("Make zip"); // create the second message part MimeBodyPart mbp2 = new MimeBodyPart(); mbp2 = zipAttachment(zipFileName, mailOptions, tempFolder); - mp.addBodyPart(mbp2); + mp.addBodyPart(mbp2); } else{ logger.debug("Attach single files"); @@ -372,7 +274,7 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe logger.debug("Attach file "+entries[i]); File f = new File(tempFolder+File.separator+entries[i]); - byte[] content = getBytesFromFile(f); + byte[] content = getBytesFromFile(f); bodyPart = new MimeBodyPart(); @@ -396,27 +298,16 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe // add the Multipart to the message msg.setContent(mp); logger.debug("Preparing to send mail"); + // send message - if ((smtpssl.equals("true")) && (!StringUtilities.isEmpty(user)) && (!StringUtilities.isEmpty(pass))){ - logger.debug("Smtps mode active user "+user); - //USE SSL Transport comunication with SMTPS - Transport transport = session.getTransport("smtps"); - transport.connect(smtphost,smtpPort,user,pass); - transport.sendMessage(msg, msg.getAllRecipients()); - transport.close(); - } - else { - logger.debug("Smtp mode"); - //Use normal SMTP - Transport.send(msg); - } - - logger.info("Mail sent for documents with labels ["+allDocumentLabels+"]"); - + facade.sendMessage(msg); + + logger.info("Mail sent for documents with labels ["+allDocumentLabels+"]"); + // logger.debug("delete tempFolder path "+tempFolder.getPath()); // boolean deleted = tempFolder.delete(); // logger.debug("Temp folder deleted "+deleted); - + } catch (Exception e) { logger.error("Error while sending schedule result mail",e); return false; @@ -431,7 +322,7 @@ public boolean sendFiles(Map mailOptions, String allDocumentLabe public static MimeBodyPart zipAttachment( String zipFileName, Map mailOptions, File tempFolder) - { + { logger.debug("IN"); MimeBodyPart messageBodyPart = null; try @@ -466,7 +357,7 @@ public static MimeBodyPart zipAttachment( String zipFileName, Map mailOptions, F out.putNextEntry(entry); // Store entry while ((bytesRead = in.read(buffer)) != -1) out.write(buffer, 0, bytesRead); - in.close(); + in.close(); } out.close(); @@ -490,7 +381,7 @@ public static MimeBodyPart zipAttachment( String zipFileName, Map mailOptions, F } private byte[] zipDocument(String fileZipName, byte[] content) { - logger.debug("IN"); + logger.debug("IN"); ByteArrayOutputStream bos=null; ZipOutputStream zos=null; @@ -515,21 +406,21 @@ private byte[] zipDocument(String fileZipName, byte[] content) { return null; }finally{ if (bos != null) { - try { + try { bos.close(); } catch (IOException e) { logger.error("Error closing output stream", e); } } if (zos != null) { - try { + try { zos.close(); } catch (IOException e) { logger.error("Error closing output stream", e); } } if (in != null) { - try { + try { in.close(); } catch (IOException e) { logger.error("Error closing output stream", e); @@ -674,15 +565,15 @@ private static List findRecipientsFromDataSet(DispatchContext info, BIOb String recipient = null; IRecord record = (IRecord)it.next(); // the parameter value is used to filter on the first dataset field - IField valueField = (IField) record.getFieldAt(0); + IField valueField = record.getFieldAt(0); Object valueObj = valueField.getValue(); String value = null; - if (valueObj != null) + if (valueObj != null) value = valueObj.toString(); if (codeValue.equals(value)) { logger.debug("Found value [" + codeValue + "] on the first field of a record of the dataset."); // recipient address is on the second dataset field - IField recipientField = (IField) record.getFieldAt(1); + IField recipientField = record.getFieldAt(1); Object recipientFieldObj = recipientField.getValue(); if (recipientFieldObj != null) { recipient = recipientFieldObj.toString(); @@ -706,42 +597,29 @@ private static List findRecipientsFromDataSet(DispatchContext info, BIOb return recipients; } - private class SMTPAuthenticator extends javax.mail.Authenticator - { - private String username = ""; - private String password = ""; - - public PasswordAuthentication getPasswordAuthentication() - { - return new PasswordAuthentication(username, password); - } - - public SMTPAuthenticator(String user, String pass) { - this.username = user; - this.password = pass; - } - } - - private class SchedulerDataSource implements DataSource { byte[] content = null; String name = null; String contentType = null; + @Override public String getContentType() { return contentType; } + @Override public InputStream getInputStream() throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(content); return bais; } + @Override public String getName() { return name; } + @Override public OutputStream getOutputStream() throws IOException { return null; } @@ -757,7 +635,7 @@ public SchedulerDataSource(byte[] content, String contentType, String name) { // Returns the contents of the file in a byte array. - public static byte[] getBytesFromFile(File file) throws IOException { + public static byte[] getBytesFromFile(File file) throws IOException { // Get the size of the file long length = file.length(); diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/init/ResourceExportFolderSchedulerInitializer.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/init/ResourceExportFolderSchedulerInitializer.java new file mode 100644 index 00000000000..570bff64362 --- /dev/null +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/init/ResourceExportFolderSchedulerInitializer.java @@ -0,0 +1,119 @@ +package it.eng.spagobi.tools.scheduler.init; + +import org.apache.log4j.Logger; + +import it.eng.spago.base.SourceBean; +import it.eng.spago.init.InitializerIFace; +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.tools.scheduler.bo.Job; +import it.eng.spagobi.tools.scheduler.bo.Trigger; +import it.eng.spagobi.tools.scheduler.dao.ISchedulerDAO; +import it.eng.spagobi.tools.scheduler.jobs.ResourceExportFolderCleaningJob; +import it.eng.spagobi.tools.scheduler.utils.PredefinedCronExpression; + +public class ResourceExportFolderSchedulerInitializer implements InitializerIFace { + public static final String DEFAULT_JOB_NAME = "CleanResourceExportFolderJob"; + public static final String DEFAULT_TRIGGER_NAME = "schedule_resource_export_cleaning"; + + public static final String RESOURCE_EXPORT_FOLDER_SCHEDULING_FULL_CLEAN = "SPAGOBI.RESOURCE.EXPORT.FOLDER.SCHEDULING_FULL_CLEAN"; + + private String valueCheck = PredefinedCronExpression.DAILY.getLabel(); + + private final SourceBean _config = null; + private transient Logger logger = Logger.getLogger(ResourceExportFolderSchedulerInitializer.class); + + @Override + public void init(SourceBean config) { + logger.debug("IN"); + try { + initCleanForDefaultTenant(); + } catch (Exception e) { + } finally { + logger.debug("OUT"); + } + + } + + public void initCleanForDefaultTenant() { + + ISchedulerDAO schedulerDAO = null; + try { + logger.debug("IN"); + schedulerDAO = DAOFactory.getSchedulerDAO(); + /* Tenant is mandatory. Set DEFAULT_TENANT but job is for all the tenants */ + schedulerDAO.setTenant("DEFAULT_TENANT"); + Job jobDetail = schedulerDAO.loadJob(DEFAULT_JOB_NAME, DEFAULT_JOB_NAME); + if (jobDetail == null) { + // CREATE JOB DETAIL + jobDetail = new Job(); + jobDetail.setName(DEFAULT_JOB_NAME); + jobDetail.setGroupName(DEFAULT_JOB_NAME); + jobDetail.setDescription(DEFAULT_JOB_NAME); + jobDetail.setDurable(true); + jobDetail.setVolatile(false); + jobDetail.setRequestsRecovery(true); + jobDetail.setJobClass(ResourceExportFolderCleaningJob.class); + + schedulerDAO.insertJob(jobDetail); + logger.debug("Added job with name " + DEFAULT_JOB_NAME); + } + + Config configValue = DAOFactory.getSbiConfigDAO().loadConfigParametersByLabel(RESOURCE_EXPORT_FOLDER_SCHEDULING_FULL_CLEAN); + + if (configValue != null && configValue.isActive()) { + valueCheck = configValue.getValueCheck(); + } + + String cronExpression = getCronExpression(valueCheck); + schedulerDAO.deleteTrigger(DEFAULT_TRIGGER_NAME, DEFAULT_JOB_NAME); + if (cronExpression != null) { + String nameTrig = DEFAULT_TRIGGER_NAME; + + Trigger simpleTrigger = new Trigger(); + simpleTrigger.setName(nameTrig); + simpleTrigger.setGroupName(DEFAULT_JOB_NAME); + simpleTrigger.setJob(jobDetail); + simpleTrigger.getChronExpression().setExpression(cronExpression); + simpleTrigger.setRunImmediately(false); + + schedulerDAO.insertTrigger(simpleTrigger); + logger.debug("Added trigger with name " + DEFAULT_TRIGGER_NAME); + } else { + logger.debug("The value " + valueCheck + + " is not a valid value for schedule RESOURCE EXPORT FOLDER cleaning trigger. Please provide a valid one and restart the Server. PERIODIC RESOURCE EXPORT FOLDER CLEANING DISABLED."); + } + logger.debug("OUT"); + } catch (Exception e) { + logger.error("Error while initializing scheduler ", e); + } finally { + if (schedulerDAO != null) { + schedulerDAO.setTenant(null); + } + } + } + + private String getCronExpression(String valueCheck) { + if (valueCheck == null) { + logger.debug("This value is [" + valueCheck + "]"); + return null; + } + + for (PredefinedCronExpression value : PredefinedCronExpression.values()) { + if (valueCheck.equalsIgnoreCase(value.getLabel())) { + logger.debug("Found a predefined cron expression with label equals to [" + valueCheck + "]"); + logger.debug("The cron expression is equals to [" + value.getExpression() + "]"); + return value.getExpression(); + } + } + logger.debug("No predefined cron expression found with label equals to [" + valueCheck + "]. Returning null."); + return null; + } + + @Override + public SourceBean getConfig() { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/jobs/ResourceExportFolderCleaningJob.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/jobs/ResourceExportFolderCleaningJob.java new file mode 100644 index 00000000000..91ec235f045 --- /dev/null +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/jobs/ResourceExportFolderCleaningJob.java @@ -0,0 +1,67 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.tools.scheduler.jobs; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.quartz.Job; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.metadata.SbiTenant; +import it.eng.spagobi.tenant.Tenant; +import it.eng.spagobi.tenant.TenantManager; +import it.eng.spagobi.tools.dataset.resource.export.ResourceExportFolderCleaningManager; + +public class ResourceExportFolderCleaningJob extends AbstractSpagoBIJob implements Job { + + static private Logger logger = Logger.getLogger(ResourceExportFolderCleaningJob.class); + + @Override + public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException { + logger.debug("IN"); + try { + executeInternal(); + } finally { + logger.debug("OUT"); + } + } + + private void executeInternal() { + + logger.debug("IN"); + try { + ResourceExportFolderCleaningManager resourceExportFolderCleaningManager = new ResourceExportFolderCleaningManager(); + List allTenants = DAOFactory.getTenantsDAO().loadAllTenants(); + for (SbiTenant sbiTenant : allTenants) { + + TenantManager.setTenant(new Tenant(sbiTenant.getName())); + resourceExportFolderCleaningManager.executeCleaning(); + this.unsetTenant(); + } + + logger.debug("Resource export folder cleaning ended succesfully!"); + } catch (Exception e) { + logger.error("Error while executiong job ", e); + } finally { + logger.debug("OUT"); + } + } +} diff --git a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/utils/SchedulerUtilitiesV2.java b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/utils/SchedulerUtilitiesV2.java index 4273e54e7a0..190d372f1c3 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/utils/SchedulerUtilitiesV2.java +++ b/knowage-core/src/main/java/it/eng/spagobi/tools/scheduler/utils/SchedulerUtilitiesV2.java @@ -245,7 +245,11 @@ public static JobTrigger getJobTriggerFromJsonRequest(JSONObject jsonObject, JSO } jobTrigger.setZonedStartTime(jsonObject.optString(JobTrigger.ZONED_START_TIME)); - jobTrigger.setZonedEndTime(jsonObject.optString(JobTrigger.ZONED_END_TIME)); + try { + jobTrigger.setZonedEndTime(jsonObject.getString(JobTrigger.ZONED_END_TIME)); + } catch (JSONException e) { + // End time can be optional + } jobTrigger.setChrono(((JSONObject) jsonObject.opt(JobTrigger.CHRONO)).toString().replaceAll("\"", "'")); JSONArray ja = (JSONArray) jsonObject.opt(JobTrigger.DOCUMENTS); diff --git a/knowage-core/src/main/java/it/eng/spagobi/wapp/services/ReadHtmlFile.java b/knowage-core/src/main/java/it/eng/spagobi/wapp/services/ReadHtmlFile.java index c6f138b4297..de0e70d3ffe 100644 --- a/knowage-core/src/main/java/it/eng/spagobi/wapp/services/ReadHtmlFile.java +++ b/knowage-core/src/main/java/it/eng/spagobi/wapp/services/ReadHtmlFile.java @@ -17,6 +17,16 @@ */ package it.eng.spagobi.wapp.services; +import java.io.FileInputStream; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.hibernate.HibernateException; +import org.hibernate.Session; + +import it.eng.knowage.menu.api.MenuManagementAPI; import it.eng.spago.base.SourceBean; import it.eng.spago.dispatching.action.AbstractHttpAction; import it.eng.spago.error.EMFErrorSeverity; @@ -28,15 +38,6 @@ import it.eng.spagobi.commons.utilities.UserUtilities; import it.eng.spagobi.wapp.bo.Menu; -import java.io.FileInputStream; - -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; - -import org.apache.log4j.Logger; -import org.hibernate.HibernateException; -import org.hibernate.Session; - public class ReadHtmlFile extends AbstractHttpAction { static private Logger logger = Logger.getLogger(ReadHtmlFile.class); @@ -70,6 +71,12 @@ public void service(SourceBean serviceRequest, SourceBean serviceResponse) throw logger.debug("menuId=" + menuId); if (menuId != null) { Menu menu = DAOFactory.getMenuDAO().loadMenuByID(Integer.valueOf(menuId)); + boolean accessible = new MenuManagementAPI(UserUtilities.getUserProfile()).isAccessibleMenu(menu); + if (!accessible) { + logger.error("No role found for menu with id = " + menu.getMenuId() + ". Not allowed menu."); + throw new Exception("No role found for menu with id = " + menu.getMenuId() + ". Not allowed menu."); + } + String fileName = menu.getStaticPage(); if (fileName == null) { diff --git a/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest1.java b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest1.java new file mode 100644 index 00000000000..64421c8e5a0 --- /dev/null +++ b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest1.java @@ -0,0 +1,34 @@ +package it.eng.spagobi.tools.dataset.resource.export.test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; + +import org.junit.Before; +import org.junit.Test; + +import it.eng.spagobi.tools.dataset.resource.export.ResourceExportFolderCleaningManager; +import it.eng.spagobi.tools.dataset.resource.export.utils.ResourceExportFolderCleaningManagerUtils; + +public class ResourceExportFolderCleaningTest1 extends ResourceExportFolderCleaningTestMain { + + private static final String FOLDER_PATH = "C:\\temp\\TestMain1\\"; + private ResourceExportFolderCleaningManager resourceExportFolderCleaningManager = new ResourceExportFolderCleaningManager(); + + @Before + public void prepare() throws Exception { + ResourceExportFolderCleaningManagerUtils cleaningManagerUtils = new ResourceExportFolderCleaningManagerUtils(); + cleaningManagerUtils.createFilesUntilFolderSize(FOLDER_PATH, MAX_FOLDER_SIZE); + + resourceExportFolderCleaningManager.executeCleaning(FOLDER_PATH, MAX_FOLDER_SIZE, CLEANING_PERCENTAGE); + + } + + @Test + public void test() throws Exception { + Long actualFolderSize = resourceExportFolderCleaningManager.folderSize(new File(FOLDER_PATH)); + + assertEquals("Expected FolderSize", true, actualFolderSize < MAX_FOLDER_SIZE * (1 - CLEANING_PERCENTAGE)); + } + +} diff --git a/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest2.java b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest2.java new file mode 100644 index 00000000000..bd72359204a --- /dev/null +++ b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTest2.java @@ -0,0 +1,34 @@ +package it.eng.spagobi.tools.dataset.resource.export.test; + +import static org.junit.Assert.assertEquals; + +import java.io.File; + +import org.junit.Before; +import org.junit.Test; + +import it.eng.spagobi.tools.dataset.resource.export.ResourceExportFolderCleaningManager; +import it.eng.spagobi.tools.dataset.resource.export.utils.ResourceExportFolderCleaningManagerUtils; + +public class ResourceExportFolderCleaningTest2 extends ResourceExportFolderCleaningTestMain { + + private static final String FOLDER_PATH = "C:\\temp\\TestMain2\\"; + private ResourceExportFolderCleaningManager resourceExportFolderCleaningManager = new ResourceExportFolderCleaningManager(); + + @Before + public void prepare() throws Exception { + ResourceExportFolderCleaningManagerUtils cleaningManagerUtils = new ResourceExportFolderCleaningManagerUtils(); + cleaningManagerUtils.createFilesUntilFolderSize(FOLDER_PATH, MAX_FOLDER_SIZE - 2 * ResourceExportFolderCleaningManagerUtils.DEFAULT_FILE_SIZE); + + resourceExportFolderCleaningManager.executeCleaning(FOLDER_PATH, MAX_FOLDER_SIZE, CLEANING_PERCENTAGE); + + } + + @Test + public void test() throws Exception { + Long actualFolderSize = resourceExportFolderCleaningManager.folderSize(new File(FOLDER_PATH)); + + assertEquals("Expected FolderSize", true, actualFolderSize < MAX_FOLDER_SIZE * (1 - CLEANING_PERCENTAGE)); + } + +} diff --git a/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTestMain.java b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTestMain.java new file mode 100644 index 00000000000..7ccf74bf173 --- /dev/null +++ b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/test/ResourceExportFolderCleaningTestMain.java @@ -0,0 +1,6 @@ +package it.eng.spagobi.tools.dataset.resource.export.test; + +public class ResourceExportFolderCleaningTestMain { + protected static final Long MAX_FOLDER_SIZE = 104857600L; + protected static final Double CLEANING_PERCENTAGE = 30.0; +} diff --git a/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/utils/ResourceExportFolderCleaningManagerUtils.java b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/utils/ResourceExportFolderCleaningManagerUtils.java new file mode 100644 index 00000000000..8649529e934 --- /dev/null +++ b/knowage-core/src/test/java/it/eng/spagobi/tools/dataset/resource/export/utils/ResourceExportFolderCleaningManagerUtils.java @@ -0,0 +1,69 @@ +package it.eng.spagobi.tools.dataset.resource.export.utils; + +import java.io.File; +import java.io.RandomAccessFile; +import java.util.HashMap; +import java.util.Map; + +public class ResourceExportFolderCleaningManagerUtils { + + public static final long DEFAULT_FILE_SIZE = 10485760L; + + public boolean createSingleFile(String path, Long length) { + boolean wellCreated = false; + RandomAccessFile rafile; + try { + rafile = new RandomAccessFile(path, "rw"); + rafile.setLength(length); + wellCreated = true; + } catch (Exception e) { + e.printStackTrace(); + } + return wellCreated; + } + + public void createFilesUntilFolderSize(String folderPath, Long folderSize, Long fileSize) { + if (!new File(folderPath).exists()) { + new File(folderPath).mkdirs(); + } else { + for (File file : new File(folderPath).listFiles()) { + file.delete(); + } + new File(folderPath).delete(); + new File(folderPath).mkdirs(); + } + + Map filesMap = new HashMap(); + + Long currentFolderSize = 0L; + int i = 0; + do { + + filesMap.put(folderPath + "file_" + i++, fileSize); + + currentFolderSize += fileSize; + + } while (currentFolderSize <= folderSize); + + for (String filePath : filesMap.keySet()) { + createSingleFile(filePath, filesMap.get(filePath)); + } + + } + + public void createFilesUntilFolderSize(String folderPath, Long folderSize) { + createFilesUntilFolderSize(folderPath, folderSize, DEFAULT_FILE_SIZE); + } + + public long folderSize(File folder) { + long length = 0; + for (File file : folder.listFiles()) { + if (file.isFile()) { + length += file.length(); + } else { + length += folderSize(file); + } + } + return length; + } +} diff --git a/knowage/pom.xml b/knowage/pom.xml index c5cb954bea2..db857b0ab70 100644 --- a/knowage/pom.xml +++ b/knowage/pom.xml @@ -240,6 +240,10 @@ xalan xalan + + com.google.guava + guava + @@ -288,6 +292,13 @@ runtime + + it.eng.knowage + knowagegooglesecurityprovider + 7.2.0-SNAPSHOT + runtime + + javax.portlet portlet-api diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages.properties index bfdbb8a02a8..38cbc33b8a6 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages.properties @@ -18,7 +18,7 @@ # missing reference to referred resource #SBISet.importexport.expResources= Export resources (OLAP schemas, datamarts, ETL jobs) 100=Generic Error -10000 = Error while triyng to retrieve (%0) corresponding to (%1) with label (%2) +10000 = Error while trying to retrieve (%0) corresponding to (%1) with label (%2) 101=Cannot load data 7000=Error during export of a SVG Document 7001=Export SVG Document Error: Cannot get information about used hierarchy from the template @@ -68,7 +68,7 @@ impexp.description = Description impexp.erase = Erase impexp.file = File impexp.listAssFile = List Association Files -impexp.manageAss = Manage Assocations +impexp.manageAss = Manage Associations impexp.mandatoryAss = Mandatory Associations impexp.manualtask.birtDocsUpdate = Birt Documents: Update impexp.manualtask.datamarts = Datamart Documents: Publish and Configure @@ -131,7 +131,7 @@ SBISet.impexp.exportedParuses = Exported Parameter uses SBISet.impexp.exportedRoles = Exported roles SBISet.impexp.metadatarule1 = The system has found that some exported metadata conflict SBISet.impexp.metadatarule2 = Exported metadata can overwrite the metadata with the same unique identifier of the existing portal if the overwrite option is enabled -SBISet.impexp.metadatarule3 = You can stop the import procecure and change the metadata identifiers which cause the conflict +SBISet.impexp.metadatarule3 = You can stop the import procedure and change the metadata identifiers which cause the conflict SBISet.impexp.metadatarule4 = If you continue and the overwrite option is disabled, the system will not insert exported metadata that causes conflicts SBISet.impexp.noDSExported = No one data source exported SBISet.impexp.noEngineExported = No one engine exported diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_bg_BG.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_bg_BG.properties index bfac37f2b3f..84bb80c9afa 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_bg_BG.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_bg_BG.properties @@ -1,5 +1,4 @@ 100=Обща Грешка -10000=Възникна грешка при опита за извличане (% 0), съответстващ на (% 1) с етикет (% 2) 101=Данните не могат да се заредят 7000=Грешка при експортиране на SVG Документ 7001=Грешка в Експортирания SVG Документ\: Не може да се получи информация за използваната йерархия от шаблона\n diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_de_DE.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_de_DE.properties index 751d17ed8f6..8e374985aee 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_de_DE.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_de_DE.properties @@ -1,5 +1,4 @@ 100=Generischer Fehler -10000=Fehler bei der Abfrage von (%0) entsprechend (%1) mit Bezeichnung (%2) 101=Daten können nicht geladen werden 8001=Kann nicht mehrere exportierte Rollen der selben Systemrolle zuordnen 8002=Eine exportierte Verbindung ist keiner aktuellen Systemverbindung zugeordnet @@ -43,7 +42,6 @@ impexp.description=Beschreibung impexp.erase=Löschen impexp.file=Datei impexp.listAssFile=Zuordnungsdateien auflisten -impexp.manageAss=Zuordnungen verwalten impexp.mandatoryAss=Obligatorische Zuordnungen impexp.manualtask.birtDocsUpdate=Birt Dokumente\: Update impexp.manualtask.datamarts=Datamart Dokumente\: veröffentlichen und konfigurieren @@ -105,7 +103,6 @@ SBISet.impexp.exportedParuses=Exportierte Parameter Verwendungen SBISet.impexp.exportedRoles=Exportierte Rollen SBISet.impexp.metadatarule1=Das System hat Konflikt einiger exportierter Metadaten festgestellt SBISet.impexp.metadatarule2=Exportierte Metadaten können Metadaten mit dem selben Unique Identifier des existierenden Portals überschreiben, wenn die Option Überschreiben aktiviert ist -SBISet.impexp.metadatarule3=Sie können das Import-Verfahren anhalten und die Identifier der Metadaten ändern, die den Konflikt verursachen SBISet.impexp.metadatarule4=Wenn Sie mit deaktivierter Überschreibungs-Option fortfahren, so wird das System die importierten Metadaten, die Konflikte verursachen, nicht einfügen SBISet.impexp.noDSExported=Keine Datenquelle exportiert SBISet.impexp.noEngineExported=Keine Engine exportiert diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_es_ES.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_es_ES.properties index 968aeef79bd..018b2d47145 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_es_ES.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_es_ES.properties @@ -3,7 +3,6 @@ # # generic errors 100=Error genérico -10000=Error mientras se intentaba recuperar (%0) correspondiendo a (%1) con etiqueta (%2) 101=No se pueden cargar datos 7000=Error durante la exportación de un documento SVG 7001=Error en la exportación del documento SVG\: No puede obtenerse información de la jerarquí usada desde el template @@ -54,7 +53,6 @@ impexp.description=Descripción impexp.erase=Borrar impexp.file=Archivo impexp.listAssFile=Lista de Asociaciones de Archivos -impexp.manageAss=Gestionar Asociaciones impexp.mandatoryAss=Asociaciones obligatorias impexp.manualtask.birtDocsUpdate=Documentos Birt\: Actualizar # @@ -120,7 +118,6 @@ SBISet.impexp.exportedParuses=Usos de Parámetros Exportados SBISet.impexp.exportedRoles=Roles exportados SBISet.impexp.metadatarule1=El sistema ha detectado conflictos sobre algunos metadatos exportados SBISet.impexp.metadatarule2=Si la opción de sobreescribir está activada, los metadatos exportados pueden sobreescribir los metadatos con el mismo identificador único del portal existente. -SBISet.impexp.metadatarule3=Puede parar el proceso de importación y cambiar los identificadores de los metadatos que causan conflictos. SBISet.impexp.metadatarule4=Si continua y la opción de sobreescribir está desactivada, el sistema no insertará los metadatos que causen conflictos. SBISet.impexp.noDSExported=Ningún datasource exportado SBISet.impexp.noEngineExported=Ningún motor exportado diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_fr_FR.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_fr_FR.properties index 10ca4576788..e854cad48d2 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_fr_FR.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_fr_FR.properties @@ -1,6 +1,5 @@ # Generated by ResourceBundle Editor (http://eclipse-rbe.sourceforge.net) #translated by altic 100=Erreur générique -10000=Erreur not é (%0) en reportant to (%1) avec label (%2) 101=Impossible de charger les données 7000=Erreur pendant l'exportation du document SVG 7001=Erreur exportation document SVG\: impossible de trouver les infos concernant la hiérarchie depuis le template @@ -53,7 +52,6 @@ impexp.description=Description impexp.erase=Annuler impexp.file=Fichier impexp.listAssFile=Liste des fichiers d'association -impexp.manageAss=Gérer les Assocations impexp.mandatoryAss=Association obligatoire impexp.manualtask.birtDocsUpdate=Document Birt \: Mise à jour impexp.manualtask.datamarts=Documents de type datamart \: publication et configuration @@ -120,7 +118,6 @@ SBISet.impexp.exportedParuses=Mode d'utilisation des paramètres exporté SBISet.impexp.exportedRoles=Rôles exportés SBISet.impexp.metadatarule1=Le système a identifié des conflits sur les identifiants de certaines métadonnées exportées SBISet.impexp.metadatarule2=Si l'option de surcharge est activée, les métadonnées exportés peuvent se superposer à celles deja présentes dans le portail en cours d'utilisation -SBISet.impexp.metadatarule3=Vous pouvez arrêter la procédure d'import et changer les identifiants des métadonnées qui causent le conflit SBISet.impexp.metadatarule4=Si l'option de surcharge est désactivée, le Systeme n'insére pas les métadonnées exportés en conflict avec celles definies dans le portail en cours d'utilisation SBISet.impexp.noDSExported=Aucune data source exportée SBISet.impexp.noEngineExported=Aucun moteur exporté diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_it_IT.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_it_IT.properties index 514369f3c7e..f23acdb1624 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_it_IT.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_it_IT.properties @@ -1,6 +1,6 @@ # generic errors 100=Errore Generico -10000=Errore nel recuperare il (%0) corrispondente al (%1) con label o identificativo(%2) +10000=Errore nel recuperare il (%0) corrispondente al (%1) con label o identificativo(%2) 101=Non è possibile caricare i dati # # errors during export SVG @@ -54,7 +54,7 @@ impexp.description=Descrizione impexp.erase=Cancella impexp.file=File impexp.listAssFile=Lista dei file di Associazioni -impexp.manageAss=Gestisci Associzioni +impexp.manageAss=Gestisci Associazioni impexp.mandatoryAss=Associazioni Obbligatorie impexp.manualtask.birtDocsUpdate=Documenti Birt\: Aggiornamento # @@ -119,7 +119,7 @@ SBISet.impexp.exportedParuses=Modalità uso parametri esportate SBISet.impexp.exportedRoles=Ruoli esportati SBISet.impexp.metadatarule1=Alcuni metadati esportati possiedono lo stesso identificativo univoco di quelli definiti nella piattaforma SBISet.impexp.metadatarule2=I metadati esportati possono sovrascrivere quelli presenti nel portale corrente se si abilita l'opzione di sovrascrittura -SBISet.impexp.metadatarule3=Per risolvere i conflitti è necessario terminare la procedura di importazione e cambiare gli identificatori che causano il problema +SBISet.impexp.metadatarule3=Per risolvere i conflitti è necessario terminare la procedura di importazione e cambiare gli identificatori che causano il problema SBISet.impexp.metadatarule4=Il sistema non inserisce i metadati esportati in conflitto con quelli definiti nel portale in uso se l'opzione di sovrascrittura è disabilitata SBISet.impexp.noDSExported=Nessun data source esportato SBISet.impexp.noEngineExported=Nessun motore esportato diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_ja_JP.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_ja_JP.properties index 4e89b7691c6..0d4278fac6b 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_ja_JP.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_ja_JP.properties @@ -1,5 +1,4 @@ 100=一般エラー -10000=(%2) のラベルが付いた、(%1) に対応する (%0) の取得を試行中にエラーが発生しました。 101=データを読み込むことができません。 8001=同じシステムロールには、エクスポートしたロールをそれ以上関連付けることはできません。 8002=エクスポートした接続は、現在のシステム接続に関連付けられていません。 @@ -42,7 +41,6 @@ impexp.description=説明 impexp.erase=消去 impexp.file=ファイル impexp.listAssFile=関連付けファイルの一覧表示 -impexp.manageAss=関連付けの管理 impexp.mandatoryAss=必須の関連付け impexp.manualtask.birtDocsUpdate=Birt 文書\: 更新 impexp.manualtask.datamarts=データマート文書\: パブリッシュと設定 @@ -104,7 +102,6 @@ SBISet.impexp.exportedParuses=エクスポート済みのパラメーターの SBISet.impexp.exportedRoles=エクスポート済みのロール SBISet.impexp.metadatarule1=システムは、エクスポート済みのメタデータの競合を検出しました。 SBISet.impexp.metadatarule2=上書きオプションを有効にすると、既存のポータルで同じ一意識別子を使用しているメタデータを、エクスポートするメタデータで上書きすることができます。 -SBISet.impexp.metadatarule3=インポートの操作を停止して、競合の原因となっているメタデータの識別子を変更することができます。 SBISet.impexp.metadatarule4=操作を続行する際に上書きのオプションが無効の場合には、システムは競合の原因となっているエクスポート済みメタデータは挿入しません。 SBISet.impexp.noDSExported=エクスポート済みのデータソースは 1 つもありません。 SBISet.impexp.noEngineExported=エクスポート済みのエンジンは 1 つもありません。 diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_pt_BR.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_pt_BR.properties index b06053d6cc7..f6c09cae36b 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_pt_BR.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_pt_BR.properties @@ -1,5 +1,4 @@ 100=Erro Genérico -10000=Erro ao tentar recuperar (%0) que corresponde a (%1) com a etiqueta (%2) 101=Não é possível carregar dados 7000=Erro durante a exportação de um documento SVG 7001=Erro de Exportação de Documento SVG\: não é possível obter informações sobre a hierarquia usada no modelo @@ -49,7 +48,6 @@ impexp.description=Descrição impexp.erase=Apagar impexp.file=Arquivo impexp.listAssFile=Listar arquivos de associação -impexp.manageAss=Gerenciar associações impexp.mandatoryAss=Associações obrigatórias impexp.manualtask.birtDocsUpdate=Documentos Birt\: Atualizar impexp.manualtask.datamarts=Documentos Datamart\: Publicar e configurar @@ -112,7 +110,6 @@ SBISet.impexp.exportedParuses=Utilizações de parâmetros exportados SBISet.impexp.exportedRoles=Funções exportadas SBISet.impexp.metadatarule1=O sistema descobriu que alguns metadados exportados estão em conflito SBISet.impexp.metadatarule2=Os metadados exportados podem substituir os metadados com o mesmo identificador exclusivo do portal existente se a opção de sobrescrever estiver ativada -SBISet.impexp.metadatarule3=Você pode interromper o procedimento de importação e alterar os identificadores de metadados que causam o conflito SBISet.impexp.metadatarule4=Se você continuar e a opção de substituição estiver desativada, o sistema não inserirá metadados exportados que causem conflitos SBISet.impexp.noDSExported=Nenhuma fonte de dados exportada SBISet.impexp.noEngineExported=Nenhuma engine exportada diff --git a/knowage/src/main/resources/MessageFiles/component_impexp_messages_zh_Hans_CN.properties b/knowage/src/main/resources/MessageFiles/component_impexp_messages_zh_Hans_CN.properties index 763c7156be8..db09874e9e2 100644 --- a/knowage/src/main/resources/MessageFiles/component_impexp_messages_zh_Hans_CN.properties +++ b/knowage/src/main/resources/MessageFiles/component_impexp_messages_zh_Hans_CN.properties @@ -1,8 +1,5 @@ # generic errors 100=一般错误 -# -# missing reference to referred resource -10000=试图检索与带有标签(%2)的(%1)相符的(%0)时发生错误 101=无法加载数据 # # errors during export SVG @@ -59,7 +56,6 @@ impexp.description=描述 impexp.erase=删除 impexp.file=文件 impexp.listAssFile=列表关联文件 -impexp.manageAss=管理关联 impexp.mandatoryAss=必填的关联 impexp.manualtask.birtDocsUpdate=Birt文档\: 更新 # SBISet.importexport.expResources= Export resources (OLAP schemas, datamarts, ETL jobs) @@ -123,7 +119,6 @@ SBISet.impexp.exportedParuses=导出的参数使用 SBISet.impexp.exportedRoles=导出角色 SBISet.impexp.metadatarule1=系统发现一些导出的元数据有冲突 SBISet.impexp.metadatarule2=如果覆盖的选项可用,导出的元数据能够覆盖有相同唯一的现存门户的识别符的元数据 -SBISet.impexp.metadatarule3=您可以停止导入过程并更改引发冲突的元数据识别符 SBISet.impexp.metadatarule4=如果您继续而覆盖选项不可用, 系统不会插入导入的引发冲突的元数据 SBISet.impexp.noDSExported=没有导出数据源 SBISet.impexp.noEngineExported=没有导出引擎 diff --git a/knowage/src/main/resources/MessageFiles/messages.properties b/knowage/src/main/resources/MessageFiles/messages.properties index 7df8bb3a75e..d24d2f025cf 100644 --- a/knowage/src/main/resources/MessageFiles/messages.properties +++ b/knowage/src/main/resources/MessageFiles/messages.properties @@ -618,6 +618,8 @@ Admintools.listModalitiesValueModule_Name = MODALITIES VALUE MANAGEMENT authError = Authentication Error! changePwd = Change Password changePwd.pwdChanged = Password changed +change_password_here = Change Password Here +old_enc_method_message = Due to the improvement of the security policy, it is necessary to change the password. CheckboxTag.showChecked = View only checked elements community.accept.mail.1 = Dear community.accept.mail.2 = user @@ -900,7 +902,7 @@ newKpi.target.invalidPeriod = Invalid period newKpi.threshold.mandatory = Threshold is mandatory newKpi.threshold.name.mandatory = Threshold Name is mandatory newKpi.threshold.type.mandatory = Threshold Type is mandatory -newKpi.threshold.values.mandatory = Error. There are no threshold values +newKpi.threshold.values.mandatory = There are no threshold values noAccount = You don't have an account? old_password = Old Password password = Password @@ -2288,7 +2290,7 @@ tree.objectstree.update = Update tree.rootfolder.description = Functionalities (Areas) tree.rootfolder.name = Functionalities (Areas) username = User Name -userPwdInvalid = User or password invalid +userPwdInvalid = Invalid username or password, try again. If the problem persists, contact the administrator: your account may have been blocked due to the maximum number of failed login attempts weka.execution.documentDetails = Document weka.execution.executionKo = Execution of Weka flow terminated with errors. weka.execution.executionOk = Execution of Weka flow successfully terminated! diff --git a/knowage/src/main/resources/MessageFiles/messages_es_ES.properties b/knowage/src/main/resources/MessageFiles/messages_es_ES.properties index 79d5cbc8422..123fd51a261 100644 --- a/knowage/src/main/resources/MessageFiles/messages_es_ES.properties +++ b/knowage/src/main/resources/MessageFiles/messages_es_ES.properties @@ -592,7 +592,6 @@ newKpi.target.invalidPeriod=Periodo invalido newKpi.threshold.mandatory=El umbral es obligatorio newKpi.threshold.name.mandatory=El umbral es obligatorio newKpi.threshold.type.mandatory=El tipo del umbral es obligatorio -newKpi.threshold.values.mandatory=Error. No hay valores de umbral noAccount=¿No tienes una cuenta? old_password=Contraseña anterior password=Contraseña @@ -1964,7 +1963,6 @@ tree.objectstree.update=Actualizar tree.rootfolder.description=Funcionalidades (Áreas) tree.rootfolder.name=Funcionalidades (Áreas) username=Nombre Usuario -userPwdInvalid=Usuario o contraseña inavalido weka.execution.documentDetails=Documento weka.execution.executionKo=La ejecución del flujo de Weka finalizó con errores weka.execution.executionOk=La ejecución del flujo de Weka finalizó con éxito\! diff --git a/knowage/src/main/resources/MessageFiles/messages_fr_FR.properties b/knowage/src/main/resources/MessageFiles/messages_fr_FR.properties index e5979f08aa9..276398b3f7d 100644 --- a/knowage/src/main/resources/MessageFiles/messages_fr_FR.properties +++ b/knowage/src/main/resources/MessageFiles/messages_fr_FR.properties @@ -595,7 +595,6 @@ newKpi.target.invalidPeriod=Période invalide newKpi.threshold.mandatory=Seuil obligatoire newKpi.threshold.name.mandatory=Nom de seuil obligatoire newKpi.threshold.type.mandatory=Type de seuil obligatoire -newKpi.threshold.values.mandatory=Erreur\: il n'y a pas des valeurs seuil noAccount=Pas de compte ? old_password=Ancien mot de passe password=Mot de passe @@ -1983,7 +1982,6 @@ tree.objectstree.update=Modifier tree.rootfolder.description=Fonctionnalités (Espace) tree.rootfolder.name=Fonctionnalités (Espace) username=Nom Utilisateur -userPwdInvalid=Identifiant ou mot-de-passe invalide weka.execution.documentDetails=Document weka.execution.executionKo=Exécution du flux weka terminée avec des erreurs weka.execution.executionOk=Exécution du flux Weka terminée avec succès \! diff --git a/knowage/src/main/resources/MessageFiles/messages_it_IT.properties b/knowage/src/main/resources/MessageFiles/messages_it_IT.properties index 87ec9af7822..072cc312967 100644 --- a/knowage/src/main/resources/MessageFiles/messages_it_IT.properties +++ b/knowage/src/main/resources/MessageFiles/messages_it_IT.properties @@ -336,6 +336,8 @@ Admintools.listModalitiesValueModule_Name=GESTIONE DEI VALORE DELLA MODALITA authError=Errore di autenticazione\! changePwd=Cambia Password changePwd.pwdChanged=Password cambiata +change_password_here=Cambia password qui +old_enc_method_message=A causa del miglioramento della politica di sicurezza, è necessario cambiare la password. CheckboxTag.showChecked=Visualizza solo gli elementi selezionati community.accept.mail.1=Caro community.accept.mail.2=utente @@ -633,7 +635,7 @@ newKpi.target.invalidPeriod=Periodo non valido newKpi.threshold.mandatory=Soglia obbligatoria newKpi.threshold.name.mandatory=Nome di soglia obbligatorio newKpi.threshold.type.mandatory=Tipo di soglia obbligatorio -newKpi.threshold.values.mandatory=Errore. No ci sono valori di soglia +newKpi.threshold.values.mandatory=Errore. Non esistono valori di soglia noAccount=Non hai un account? old_password=Vecchia Password password=Password @@ -2058,7 +2060,7 @@ tree.objectstree.update=Aggiorna tree.rootfolder.description=Funzionalità (Aree) tree.rootfolder.name=Funzionalità (Aree) username=Nome Utente -userPwdInvalid=User o password non valida +userPwdInvalid=Username o password non validi, riprovare. Se il problema persiste, contattare l'amministratore\: il tuo account potrebbe essere stato bloccato a causa del numero massimo di tentativi di accesso non riusciti. weka.execution.documentDetails=Documento weka.execution.executionKo=Esecuzione dell'analisi Weka terminata con errori. weka.execution.executionOk=Esecuzione dell'analisi Weka terminata con successo\! diff --git a/knowage/src/main/resources/MessageFiles/messages_pt_BR.properties b/knowage/src/main/resources/MessageFiles/messages_pt_BR.properties index 283fd5a511d..011b0f52fab 100644 --- a/knowage/src/main/resources/MessageFiles/messages_pt_BR.properties +++ b/knowage/src/main/resources/MessageFiles/messages_pt_BR.properties @@ -1484,7 +1484,6 @@ tree.objectstree.update=Atualizar tree.rootfolder.description=Recursos (áreas) tree.rootfolder.name=Recursos (áreas) username=Nome do usuário -userPwdInvalid=Usuário ou senha inválidos weka.execution.documentDetails=Documento weka.execution.noRelatedDocuments=Nenhum documento relacionado weka.execution.parameters=Execução de controladores analíticos\: diff --git a/knowage/src/main/resources/MessageFiles/messages_zh_Hans_CN.properties b/knowage/src/main/resources/MessageFiles/messages_zh_Hans_CN.properties index 768f2e8c32f..8cbf1dfa571 100644 --- a/knowage/src/main/resources/MessageFiles/messages_zh_Hans_CN.properties +++ b/knowage/src/main/resources/MessageFiles/messages_zh_Hans_CN.properties @@ -589,7 +589,6 @@ newKpi.target.invalidPeriod=无效的周期 newKpi.threshold.mandatory=阈值必填 newKpi.threshold.name.mandatory=阈值名称必填 newKpi.threshold.type.mandatory=阈值类型必填 -newKpi.threshold.values.mandatory=错误.没有阈值 noAccount=您没有账户吗? old_password=旧密码 password=密码 @@ -1987,7 +1986,6 @@ tree.objectstree.update=更新 tree.rootfolder.description=功能 (区域) tree.rootfolder.name=功能 (区域) username=用户名 -userPwdInvalid=用户或密码无效 weka.execution.documentDetails=文档 weka.execution.executionKo=Weka流的执行以错误结束. weka.execution.executionOk=Weka流的执行成功结束\! diff --git a/knowage/src/main/resources/ehcache.xml b/knowage/src/main/resources/ehcache.xml index 183eab61a6e..e69f1222a49 100644 --- a/knowage/src/main/resources/ehcache.xml +++ b/knowage/src/main/resources/ehcache.xml @@ -15,6 +15,10 @@ + diskPersistent="false" diskExpiryThreadIntervalSeconds="3" /> + + diff --git a/knowage/src/main/resources/hsql/hibernate.cfg.xml b/knowage/src/main/resources/hsql/hibernate.cfg.xml index 8e8f9f86c23..cdc65caa3ad 100644 --- a/knowage/src/main/resources/hsql/hibernate.cfg.xml +++ b/knowage/src/main/resources/hsql/hibernate.cfg.xml @@ -27,6 +27,7 @@ false + org.hibernate.jdbc.NonBatchingBatcherFactory + + + diff --git a/knowage/src/main/webapp/WEB-INF/conf/config/internal_profiling.xml b/knowage/src/main/webapp/WEB-INF/conf/config/internal_profiling.xml index 4800d59f952..d19201fb1ce 100644 --- a/knowage/src/main/webapp/WEB-INF/conf/config/internal_profiling.xml +++ b/knowage/src/main/webapp/WEB-INF/conf/config/internal_profiling.xml @@ -90,6 +90,7 @@ + @@ -117,6 +118,8 @@ + + @@ -133,6 +136,7 @@ + @@ -155,6 +159,7 @@ + @@ -180,12 +185,13 @@ + - + @@ -202,5 +208,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/knowage/src/main/webapp/WEB-INF/jsp/commons/preview.jsp b/knowage/src/main/webapp/WEB-INF/jsp/commons/preview.jsp index 10e2e43a846..ee50f140550 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/commons/preview.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/commons/preview.jsp @@ -16,15 +16,41 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . --%> <%@page import="it.eng.spagobi.commons.utilities.GeneralUtilities"%> +<%@page import="it.eng.spagobi.commons.utilities.urls.IUrlBuilder"%> +<%@page import="it.eng.spagobi.commons.utilities.urls.UrlBuilderFactory"%> +<%@page import="it.eng.spago.base.*"%> +<% + RequestContainer aRequestContainer = null; + IUrlBuilder urlBuilder = null; + String sbiMode = null; + + // case of portlet mode + aRequestContainer = RequestContainerPortletAccess.getRequestContainer(request); + if (aRequestContainer == null) { + // case of web mode + aRequestContainer = RequestContainer.getRequestContainer(); + if(aRequestContainer == null){ + //case of REST + aRequestContainer = RequestContainerAccess.getRequestContainer(request); + } + } + + String channelType = aRequestContainer.getChannelType(); + if ("PORTLET".equalsIgnoreCase(channelType)) sbiMode = "PORTLET"; + else sbiMode = "WEB"; + + // create url builder + urlBuilder = UrlBuilderFactory.getUrlBuilder(sbiMode); +%> - + "> - + "> + @@ -1118,18 +1119,27 @@ div.lower i { - - + + - + + + Python + R + + + + + - + - - {{e.label}} + {{e.label}} + {{e.label}}
@@ -1138,13 +1148,14 @@ div.lower i { - {{translate.load("sbi.ds.python.checkEnvironment")}} + {{translate.load("sbi.ds.python.checkEnvironment")}} + {{translate.load("sbi.ds.python.checkEnvironment")}}
- -
+ +
{{translate.load("sbi.catalogues.generic.reqired");}}
@@ -1153,12 +1164,12 @@ div.lower i { - -
+
{{translate.load("sbi.catalogues.generic.reqired");}}
@@ -1735,27 +1746,22 @@ div.lower i { - +
-
- - - - - +
-
diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/lovsManagement.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/lovsManagement.jsp index a539d844471..f46f7ad7f17 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/lovsManagement.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/lovsManagement.jsp @@ -1,351 +1,295 @@ <%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - + Knowage, Open Source Business Intelligence suite + Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + + Knowage is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Knowage 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + --%> - + The main JSP page for the management of the LOV catalog. + + Author: Danilo Ristovski (danristo, danilo.ristovski@mht.net) + Author: Stefan Petrovic (spetrovic, Stefan.Petrovic@mht.net) + --> <%@ page language="java" pageEncoding="UTF-8" session="true"%> - <%-- ---------------------------------------------------------------------- --%> <%-- JAVA IMPORTS --%> <%-- ---------------------------------------------------------------------- --%> <%@include file="/WEB-INF/jsp/commons/angular/angularResource.jspf"%> - - - - - - - - - - <%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> - - "> - - - - -"> -"> - - -" /> - - - - - - - - - - LOVS Management - - - - - - - - - - - - - - - - - - - - - - - {{translate.load("sbi.ds.test")}} - - - - {{translate.load("sbi.datasource.testing")}} - - - - {{translate.load("sbi.generic.save")}} - - - -
- - -
-
- - - - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
- -
-
-
- -
-
- - - - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
- - -
-
-
- -
-
- - - - -
-
- -
-
- - - {{l.VALUE_NM}} - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
-
-
-
- -
- - - -
-

- {{toolbarTitle}} -

- - - - - - - - - -
-
- -
-
-
- - - {{l.VALUE_NM}} - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
-
-
-
- - - - - - -
- -
-
-
- - - {{l.label}} - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
-
-
-
- - - - - -
- -
- -
-
- - - - - -
-
- -
-
- - - - - -
-
-
- {{translate.load("sbi.generic.save");}} -
- - -
- - - - - - -
-
- -
- -
-
- - - - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
- -
-
-
- -
- -
- -
- - - - - - - - - - {{::translate.load("sbi.functionscatalog.adddataset")}} - - -
-
- -
-
- -
-
-
- - - + + + + + <%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> + "> + + + "> + "> + + + " /> + + + + + + + + LOVS Management + + + + + + + + + + + + + + {{translate.load("sbi.ds.test")}} + + + {{translate.load("sbi.datasource.testing")}} + + + {{translate.load("sbi.generic.save")}} + + +
+ +
+
+ + + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
{{translate.load("sbi.behavioural.lov.errorLabelNotValid");}}
+
+
+
+
+
+
+ + + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
{{translate.load("sbi.behavioural.lov.errorNameNotValid");}}
+
+
+
+
+
+
+ + + + +
+
+
+
+ + + + {{l.VALUE_NM}} + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+
+ + +
+

+ {{toolbarTitle}} +

+ + + + + + + +
+
+ +
+
+
+ + + + {{l.VALUE_NM}} + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+ + + + +
+
+
+
+ + + + {{l.label}} + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+
+ + + + +
+
+
+ + {{translate.load("sbi.generic.save");}} +
+
+ + +
+
+
+
+
+ + + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+
+
+
+ + + + + + + + + + {{::translate.load("sbi.functionscatalog.adddataset")}} + + +
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/rolesManagement.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/rolesManagement.jsp index 9b787ed2bfc..9a24aac16a7 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/rolesManagement.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/rolesManagement.jsp @@ -421,7 +421,16 @@ along with this program. If not, see .
- +
+ + + + +
+ +
+
{{translate.load("sbi.roles.finalUserCan");}} diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/usersManagement.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/usersManagement.jsp index 154a00b79a9..49ac131f378 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/usersManagement.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/catalogue/usersManagement.jsp @@ -1,193 +1,172 @@ <%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - + Knowage, Open Source Business Intelligence suite + Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + + Knowage is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Knowage 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + --%> <%@ page language="java" pageEncoding="UTF-8" session="true"%> - <%-- ---------------------------------------------------------------------- --%> <%-- JAVA IMPORTS --%> <%-- ---------------------------------------------------------------------- --%> - <%@include file="/WEB-INF/jsp/commons/angular/angularResource.jspf"%> - -<%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> - -"> - - - -Users Management - -<% - Boolean isSSOEnabledH = GeneralUtilities.isSSOEnabled(); -%> - - - - <%if(includeInfusion){ %> - <%@include file="/WEB-INF/jsp/commons/infusion/infusionTemplate.html"%> - <%} %> - - - - - - - - -
-
- - - - - - -
- - - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
-
-
-
- - - -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
-
-
-
- - ng-required="passwordRequired" <%}%> - ng-maxlength="100" autocomplete="new-password"> - - <%if(isSSOEnabledH == null || isSSOEnabledH == false){ %> -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
- <%}%> -
-
- -
- - ng-required="passwordRequired" <%}%> - ng-maxlength="100" nx-equal-ex="selectedUser.password" autocomplete="new-password"> - - <%if(isSSOEnabledH == null || isSSOEnabledH == false){ %> -
-
{{translate.load("sbi.catalogues.generic.reqired");}}
-
- <%}%> - -
-
{{translate.load("sbi.users.pwdNotMatching");}}
-
-
-
-
-
-
- - - - -
-
{{translate.load("sbi.catalogues.generic.reqired.role");}}
-
-
- -
- - - - - - {{ opt.name }} - - -
- {{translate.load("sbi.users.defaultRoleHint")}} -
-
-
- -
- -
-
-
- - - -
-
- - -
-
-
-
- - - - -
-
- - - -
-
-
-
-
-
-
- -
-
-
-
- - + + <%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> + + "> + + + Users Management + <% + Boolean isSSOEnabledH = GeneralUtilities.isSSOEnabled(); + %> + + + <%if(includeInfusion){ %> + <%@include file="/WEB-INF/jsp/commons/infusion/infusionTemplate.html"%> + <%} %> + + + + + + +
+
+ + + + +
+
+ {{translate.load("sbi.users.lockedByMaxFailedLoginAttempts")}} +
+ + {{translate.load("sbi.users.unlockUser")}} + +
+
+ + + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+ + + +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+
+
+
+ + + ng-required="passwordRequired" + <%}%> + ng-maxlength="100" autocomplete="new-password"> + + <%if(isSSOEnabledH == null || isSSOEnabledH == false){ %> +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+ <%}%> +
+
+
+ + + ng-required="passwordRequired" + <%}%> + ng-maxlength="100" nx-equal-ex="selectedUser.password" autocomplete="new-password"> + + <%if(isSSOEnabledH == null || isSSOEnabledH == false){ %> +
+
{{translate.load("sbi.catalogues.generic.reqired");}}
+
+ <%}%> +
+
{{translate.load("sbi.users.pwdNotMatching");}}
+
+
+
+
+
+
+ + + + +
+
{{translate.load("sbi.catalogues.generic.reqired.role");}}
+
+
+
+ + + + + + {{ opt.name }} + + +
+ {{translate.load("sbi.users.defaultRoleHint")}} +
+
+
+
+
+
+
+ + + +
+
+ + + +
+
+
+
+
+ + + + +
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentbrowser/templates/documentBrowserTemplate.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentbrowser/templates/documentBrowserTemplate.jsp index d650f6b9e5f..f46440b044a 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentbrowser/templates/documentBrowserTemplate.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentbrowser/templates/documentBrowserTemplate.jsp @@ -221,7 +221,7 @@ along with this program. If not, see .
-
+
diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionMaster.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionMaster.jsp index 75d9215e5f6..c2664e63265 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionMaster.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionMaster.jsp @@ -84,6 +84,13 @@ along with this program. If not, see . String cockpitParameters = request.getParameter("COCKPIT_PARAMETER") != null ? request.getParameter("COCKPIT_PARAMETER") : "null"; %> + /* + * Validation check for exec_from variable for security reasons + */ + var execFrom = '<%=request.getParameter("EXEC_FROM")%>'; + if (execFrom !='WORKSPACE_ORGANIZER') { + execFrom = null; + } var obj = { 'OBJECT_ID' : '<%=request.getParameter("OBJECT_ID") != null @@ -101,7 +108,7 @@ along with this program. If not, see . 'EDIT_MODE': '<%=request.getParameter("EDIT_MODE") != null ? request.getParameter("EDIT_MODE") : aRequestContainer.getServiceRequest().getAttribute("EDIT_MODE")%>', - 'EXEC_FROM': '<%=request.getParameter("EXEC_FROM")%>', + 'EXEC_FROM': execFrom, 'COCKPIT_PARAMETER' : '<%=cockpitParameters.replaceAll(Pattern.quote("'"), Matcher.quoteReplacement("\\'"))%>', 'IS_FROM_DOCUMENT_WIDGET' : '<%=request.getParameter("IS_FROM_DOCUMENT_WIDGET")%>', 'TOOLBAR_VISIBLE' : '<%=request.getParameter("TOOLBAR_VISIBLE")%>', @@ -110,7 +117,6 @@ along with this program. If not, see . }; - <% if (request.getParameter("SELECTED_ROLE") != null && !request.getParameter("SELECTED_ROLE").equalsIgnoreCase("")) {%> diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionNg.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionNg.jsp index f1e5303e96b..5986c1c4a5b 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionNg.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/documentexecution/documentExecutionNg.jsp @@ -76,7 +76,15 @@ try{ @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ executedFrom = (String)(request.getParameter("EXEC_FROM")); - + + /* + * Validation check for exec_from variable for security reasons + */ + + if (!"WORKSPACE_ORGANIZER".equals(executedFrom)) { + executedFrom = null; + } + isFromDocumentWidget = (String)(request.getParameter("IS_FROM_DOCUMENT_WIDGET")); isForExport = (String)(request.getParameter(SpagoBIConstants.IS_FOR_EXPORT)); if(isForExport == null) { @@ -237,12 +245,12 @@ if(executionRoleNames.size() > 0) { <% if(engineName.equalsIgnoreCase( SpagoBIConstants.COCKPIT_ENGINE_NAME) && (isAdmin || userId.equals(obj.getCreationUser()))) {%> - {{::translate.load('sbi.execution.executionpage.toolbar.viewcockpitdoc')}} - {{::translate.load('sbi.execution.executionpage.toolbar.editcockpitdoc')}} @@ -596,7 +604,6 @@ if(executionRoleNames.size() > 0) { var newUrl = cockpitEditingService.changeDocumentExecutionUrlParameter('documentMode', cockpitEditingService.documentMode); execProperties.documentUrl = newUrl; };*/ - cockpitEditingService.documentMode = 'VIEW'; if(document.getElementById('postForm_documentMode').value == 'EDIT'){ var confirm = $mdDialog.confirm() @@ -606,6 +613,7 @@ if(executionRoleNames.size() > 0) { .ok(sbiModule_translate.load("sbi.general.continue")) .cancel(sbiModule_translate.load("sbi.general.cancel")); $mdDialog.show(confirm).then(function(){ + cockpitEditingService.documentMode = 'VIEW'; document.getElementById('postForm_documentMode').value = cockpitEditingService.documentMode; document.getElementById('postForm_'+execProperties.executionInstance.OBJECT_ID).submit(); }); diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/glossary/businessuser/glossaryBusiness.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/glossary/businessuser/glossaryBusiness.jsp index 345ae214c34..d02757d04c2 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/glossary/businessuser/glossaryBusiness.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/glossary/businessuser/glossaryBusiness.jsp @@ -114,13 +114,7 @@ along with this program. If not, see . - - {{translate.load("sbi.generic.safeMode");}} - - + diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/multitenant/multitenantManagementAngular.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/multitenant/multitenantManagementAngular.jsp index 12461c243d1..e4d80a4801f 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/multitenant/multitenantManagementAngular.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/multitenant/multitenantManagementAngular.jsp @@ -78,7 +78,7 @@ along with this program. If not, see .
- +
diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/scheduler/JobManagement.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/scheduler/JobManagement.jsp index 7104d485222..721948f7725 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/scheduler/JobManagement.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/scheduler/JobManagement.jsp @@ -156,6 +156,14 @@ along with this program. If not, see .
{{::translate.load('scheduler.jobhasnodocument')}}
+
+
+
+ The following parameters are not present anymore in the original document and will be removed from this scheduled document: +
{{param.name}}
+
+
+
{{parameter.name}} diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportDocuments/importDocumentsSteps/importDocumentsStep4.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportDocuments/importDocumentsSteps/importDocumentsStep4.jsp index d916e4869a8..563cf0fb0d8 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportDocuments/importDocumentsSteps/importDocumentsStep4.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportDocuments/importDocumentsSteps/importDocumentsStep4.jsp @@ -23,7 +23,7 @@ --> {{translate.load('SBISet.start.import','component_impexp_messages');}}
-
+
{{translate.load('SBISet.importexport.notImportableDocuments','component_impexp_messages');}}
diff --git a/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportMenu/importMenuSteps/importMenuStep1.jsp b/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportMenu/importMenuSteps/importMenuStep1.jsp index 8abc6697917..ba4e7081783 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportMenu/importMenuSteps/importMenuStep1.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/tools/servermanager/importExportMenu/importMenuSteps/importMenuStep1.jsp @@ -24,7 +24,8 @@

{{translate.load('sbi.hierarchies.source');}}

{{translate.load('sbi.modelinstances.target');}}

- {{translate.load('SBISet.impexp.exportedMenu','component_impexp_messages');}} + +
diff --git a/knowage/src/main/webapp/WEB-INF/jsp/wapp/changePwd.jsp b/knowage/src/main/webapp/WEB-INF/jsp/wapp/changePwd.jsp index a4a6a7626e1..61dc3c9f20e 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/wapp/changePwd.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/wapp/changePwd.jsp @@ -37,36 +37,44 @@ along with this program. If not, see . <%@page import="java.util.Map"%> <% - String userId = (request.getParameter("user_id")==null)?"":request.getParameter("user_id"); + String userId = (request.getParameter("user_id") == null) ? "" : request.getParameter("user_id"); String contextName = ChannelUtilities.getSpagoBIContextName(request); - String authFailed = (request.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE) == null)?"": - (String)request.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE); + String authFailed = (request.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE) == null) ? "" + : (String) request.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE); + + String oldEncMethodMessage = (request.getParameter("old_enc_method_message") == null) ? "" : request.getParameter("old_enc_method_message"); ResponseContainer responseContainer = ResponseContainerAccess.getResponseContainer(request); RequestContainer requestContainer = RequestContainer.getRequestContainer(); - String currTheme=ThemesManager.getDefaultTheme(); - if (requestContainer != null){ - currTheme=ThemesManager.getCurrentTheme(requestContainer); - if(currTheme==null)currTheme=ThemesManager.getDefaultTheme(); + String currTheme = ThemesManager.getDefaultTheme(); + if (requestContainer != null) { + currTheme = ThemesManager.getCurrentTheme(requestContainer); + if (currTheme == null) + currTheme = ThemesManager.getDefaultTheme(); - if(responseContainer!=null) { + if (responseContainer != null) { SourceBean aServiceResponse = responseContainer.getServiceResponse(); - if(aServiceResponse!=null) { - SourceBean loginModuleResponse = (SourceBean)aServiceResponse.getAttribute("LoginModule"); - if(loginModuleResponse!=null) { - userId = (String)loginModuleResponse.getAttribute("user_id"); - String authFailedMessage = (String)loginModuleResponse.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE); - if(authFailedMessage!=null) authFailed = authFailedMessage; + if (aServiceResponse != null) { + SourceBean loginModuleResponse = (SourceBean) aServiceResponse.getAttribute("LoginModule"); + if (loginModuleResponse != null) { + userId = (String) loginModuleResponse.getAttribute("user_id"); + String authFailedMessage = (String) loginModuleResponse.getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE); + if (authFailedMessage != null) + authFailed = authFailedMessage; + + String tmpOldEncMethodMessage = (String) loginModuleResponse.getAttribute("old_enc_method_message"); + if (tmpOldEncMethodMessage != null) + oldEncMethodMessage = tmpOldEncMethodMessage; + } } } - } - + IMessageBuilder msgBuilder = MessageBuilderFactory.getMessageBuilder(); - + String sbiMode = "WEB"; IUrlBuilder urlBuilder = null; urlBuilder = UrlBuilderFactory.getUrlBuilder(sbiMode); @@ -74,126 +82,107 @@ along with this program. If not, see . - - - - - - Knowage - " /> - - - - "> - - - - - - - - - - "> - - - - - - - - - - - -
-
- - -

-<%-- - - -
- - - - - - - - - - - - - - - - + + + + + + Knowage + " /> + + " /> + + + + + + + + + + + "> + "> + + + + + +
+ +
+
<%=oldEncMethodMessage%>
+
+
+ +
+

+ <%-- + +
+ +
+ + + + + + + diff --git a/knowage/src/main/webapp/WEB-INF/jsp/wapp/demo_login.jsp b/knowage/src/main/webapp/WEB-INF/jsp/wapp/demo_login.jsp index 20ccf621c6e..da9d4e56515 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/wapp/demo_login.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/wapp/demo_login.jsp @@ -45,8 +45,6 @@ along with this program. If not, see . //RequestContainer requestContainer = RequestContainerAccess.getRequestContainer(request); SingletonConfig serverConfig = SingletonConfig.getInstance(); - String strInternalSecurity = serverConfig.getConfigValue("SPAGOBI.SECURITY.PORTAL-SECURITY-CLASS.className"); - boolean isInternalSecurity = (strInternalSecurity.indexOf("InternalSecurity")>0)?true:false; RequestContainer requestContainer = RequestContainer.getRequestContainer(); @@ -133,7 +131,6 @@ else {
- <% // propagates parameters (if any) for document execution if (request.getParameter(ObjectsTreeConstants.OBJECT_LABEL) != null) { diff --git a/knowage/src/main/webapp/WEB-INF/jsp/wapp/logout.jsp b/knowage/src/main/webapp/WEB-INF/jsp/wapp/logout.jsp index 1b287b3bebf..1ffcfe77ad4 100644 --- a/knowage/src/main/webapp/WEB-INF/jsp/wapp/logout.jsp +++ b/knowage/src/main/webapp/WEB-INF/jsp/wapp/logout.jsp @@ -23,6 +23,7 @@ along with this program. If not, see . <%@page import="it.eng.spagobi.commons.SingletonConfig"%> <%@page import="it.eng.spagobi.commons.constants.SpagoBIConstants"%> <%@page import="it.eng.spagobi.commons.utilities.GeneralUtilities"%> +<%@page import="it.eng.spagobi.security.google.config.GoogleSignInConfig"%> '] - , src: firstUrl - , height: '100%' - }); - Sbi.execution.ExporterUtils.setIFrame( this.mainframe ); - - this.titlePath = Ext.create("Ext.Panel",{title :'Home'}); - var itemsM = <%=jsonMenuList%>; - for(i=0; i< itemsM.length; i++){ - var menuItem = itemsM[i]; - if(menuItem.itemLabel != null && menuItem.itemLabel == "LANG"){ - var languagesMenuItems = []; - for (var j = 0; j < Sbi.config.supportedLocales.length ; j++) { - var aLocale = Sbi.config.supportedLocales[j]; - aLocale.currTheme = '<%=currTheme%>'; - var aLanguagesMenuItem = new Ext.menu.Item({ - id: '', - text: aLocale.language, - iconCls:'icon-' + aLocale.language, - href: this.getLanguageUrl(aLocale) - }) - languagesMenuItems.push(aLanguagesMenuItem); - } - menuItem.menu= languagesMenuItems; - }else if(menuItem.itemLabel != null && menuItem.itemLabel == "ROLE"){ - if(Sbi.user.roles && Sbi.user.roles.length == 1){ - menuItem.hidden=true; - } - }else if(menuItem.itemLabel != null && menuItem.itemLabel == "HOME"){ - menuItem.tooltip = '

'+LN('sbi.home.Welcome')+''+ - '

'+Sbi.user.userName+'

' - +'

' - } - - } - function hideItem( menu, e, eOpts){ - //console.log('bye bye '); - menu.hide(); - } - - - /* this.mainpanel = Ext.create("Ext.panel.Panel",{ - autoScroll: true, - height: '100%', - items: [ - //this.titlePath , - mainframe] - , dockedItems: [{ - xtype: 'toolbar', - dock: 'left', - items: itemsM - }] - }); -*/ - - <%if (isDirectExec.equals("FALSE")){%> - this.mainpanel = Ext.create("Ext.panel.Panel",{ - autoScroll: true, - height: '100%', - items: [ - //this.titlePath , - mainframe] - , dockedItems: [{ - xtype: 'toolbar', - dock: 'left', - items: itemsM - }] - }); - <%}else{%> - this.mainpanel = Ext.create("Ext.panel.Panel",{ - autoScroll: true, - height: '100%', - items: [ - //this.titlePath , - mainframe] - }); - <%}%> - - Ext.create('Ext.Viewport', { - - layout: 'fit', - items: [this.mainpanel] - }); - - -}); - - - - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/login.jsp b/knowage/src/main/webapp/themes/geobi/jsp/login.jsp deleted file mode 100644 index 87956a330ae..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/login.jsp +++ /dev/null @@ -1,232 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@ page language="java" - extends="it.eng.spago.dispatching.httpchannel.AbstractHttpJspPagePortlet" - contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" - session="true" - import="it.eng.spago.base.*, - it.eng.spagobi.commons.constants.SpagoBIConstants" -%> -<%@page import="it.eng.spagobi.commons.utilities.ChannelUtilities"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.IMessageBuilder"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.UrlBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.IUrlBuilder"%> -<%@page import="it.eng.spago.base.SourceBean"%> -<%@page import="it.eng.spago.navigation.LightNavigationManager"%> -<%@page import="it.eng.spagobi.utilities.themes.ThemesManager"%> -<%@page import="it.eng.spagobi.commons.constants.ObjectsTreeConstants"%> -<%@page import="org.apache.commons.lang.StringEscapeUtils"%> -<%@page import="java.util.Enumeration"%> - - -<% - String contextName = ChannelUtilities.getSpagoBIContextName(request); - - - String authFailed = ""; - String startUrl = ""; - ResponseContainer aResponseContainer = ResponseContainerAccess - .getResponseContainer(request); - //RequestContainer requestContainer = RequestContainerAccess.getRequestContainer(request); - RequestContainer requestContainer = RequestContainer - .getRequestContainer(); - //SessionContainer sessionContainer = requestContainer.getSessionContainer(); - - SingletonConfig serverConfig = SingletonConfig.getInstance(); - String strInternalSecurity = serverConfig - .getConfigValue("SPAGOBI.SECURITY.PORTAL-SECURITY-CLASS.className"); - boolean isInternalSecurity = (strInternalSecurity - .indexOf("InternalSecurity") > 0) ? true : false; - String roleToCheckLbl = - (SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN") == null)?"" : - SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN"); - String roleToCheckVal = ""; - if (!("").equals(roleToCheckLbl)) { - roleToCheckVal = (request.getParameter(roleToCheckLbl) != null) ? request - .getParameter(roleToCheckLbl) : ""; - if (("").equals(roleToCheckVal)) { - // roleToCheckVal = ( sessionContainer.getAttribute(roleToCheckLbl)!=null)? - // (String)sessionContainer.getAttribute(roleToCheckLbl):""; - roleToCheckVal = (session.getAttribute(roleToCheckLbl) != null) ? (String) session - .getAttribute(roleToCheckLbl) : ""; - } - } - - String currTheme = ThemesManager.getCurrentTheme(requestContainer); - if (currTheme == null) - currTheme = ThemesManager.getDefaultTheme(); - - if (aResponseContainer != null) { - SourceBean aServiceResponse = aResponseContainer - .getServiceResponse(); - if (aServiceResponse != null) { - SourceBean loginModuleResponse = (SourceBean) aServiceResponse - .getAttribute("LoginModule"); - if (loginModuleResponse != null) { - String authFailedMessage = (String) loginModuleResponse - .getAttribute(SpagoBIConstants.AUTHENTICATION_FAILED_MESSAGE); - startUrl = (loginModuleResponse.getAttribute("start_url") == null) ? "" : (String) loginModuleResponse.getAttribute("start_url"); - if (authFailedMessage != null) { - authFailed = authFailedMessage; - } - } - } - } - - IMessageBuilder msgBuilder = MessageBuilderFactory - .getMessageBuilder(); - - String sbiMode = "WEB"; - IUrlBuilder urlBuilder = null; - urlBuilder = UrlBuilderFactory.getUrlBuilder(sbiMode); -%> - - -<%@page import="it.eng.spagobi.commons.SingletonConfig"%> - - - - " /> - Knowage - - - - - - - - <% - String userDefaultValue = msgBuilder.getMessage("username",request); - String pwdDefaultValue = msgBuilder.getMessage("password",request); - %> -
-
-
-

<%=msgBuilder.getMessage("login")%>

- - - - - <% - //manages backUrl after login - String backUrl = (String)request.getAttribute(SpagoBIConstants.BACK_URL); - if (backUrl != null && !backUrl.equals("")) { - String objLabel = (String)request.getAttribute(SpagoBIConstants.OBJECT_LABEL); - backUrl += (backUrl.indexOf("?")<0)?"?":"&"; - backUrl += "fromLogin=true"; - %> - - - - - <% - } - // propagates parameters (if any) for document execution - if (request.getParameter(ObjectsTreeConstants.OBJECT_LABEL) != null) { - String label = request.getParameter(ObjectsTreeConstants.OBJECT_LABEL); - String subobjectName = request.getParameter(SpagoBIConstants.SUBOBJECT_NAME); - %> - - <% if (subobjectName != null && !subobjectName.trim().equals("")) { %> - - <% } %> - <% - // propagates other request parameters than PAGE, NEW_SESSION, OBJECT_LABEL and SUBOBJECT_NAME - Enumeration parameters = request.getParameterNames(); - while (parameters.hasMoreElements()) { - String aParameterName = (String) parameters.nextElement(); - if (aParameterName != null - && !aParameterName.equalsIgnoreCase("PAGE") && !aParameterName.equalsIgnoreCase("NEW_SESSION") - && !aParameterName.equalsIgnoreCase(ObjectsTreeConstants.OBJECT_LABEL) - && !aParameterName.equalsIgnoreCase(SpagoBIConstants.SUBOBJECT_NAME) - && request.getParameterValues(aParameterName) != null) { - String[] values = request.getParameterValues(aParameterName); - for (int i = 0; i < values.length; i++) { - %> - - <% - } - } - } - } - %> - -
-
- - -
-
- - - -
-
- " /> -

<%=msgBuilder.getMessage("noAccount")%> <%=msgBuilder.getMessage("signup")%>

- -
-
- -
-
-
- - - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/publicUserHome.jsp b/knowage/src/main/webapp/themes/geobi/jsp/publicUserHome.jsp deleted file mode 100644 index 5a692e63426..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/publicUserHome.jsp +++ /dev/null @@ -1,191 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@page language="java" - contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" -%> -<%@ include file="/WEB-INF/jsp/wapp/homeBase.jsp"%> - - -<% - String mapsUrl="#"; - String datasetUrl = "#"; - String loginUrl = "#"; - Map langUrls = new HashMap(); - - for(int i=0; i< jsonMenuList.length(); i++){ - Object menuObj = jsonMenuList.get(i); - if(menuObj instanceof JSONObject) { - JSONObject menuItem = jsonMenuList.getJSONObject(i); - - if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("folder_open")){ - mapsUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("my_data")){ - datasetUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("login")){ - loginUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("itemLabel") && menuItem.getString("itemLabel") == "LANG"){ - List localesList = GeneralUtilities.getSupportedLocales(); - for (int j = 0; j < localesList.size() ; j++) { - String langUrl = "javascript:execUrl(\\'"+contextName+"/servlet/AdapterHTTP?ACTION_NAME=CHANGE_LANGUAGE&IS_PUBLIC_USER=TRUE&THEME_NAME="+currTheme; - Locale aLocale = (Locale)localesList.get(j); - langUrl += "&LANGUAGE_ID="+aLocale.getLanguage()+"&COUNTRY_ID="+aLocale.getCountry(); - langUrl += "\\')"; - langUrls.put( aLocale.getLanguage(), langUrl); - } - } - } - } -%> - - - - - - - - - - - - - - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/signup/active.jsp b/knowage/src/main/webapp/themes/geobi/jsp/signup/active.jsp deleted file mode 100644 index 7b4c37786ea..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/signup/active.jsp +++ /dev/null @@ -1,149 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@ page language="java" - extends="it.eng.spago.dispatching.httpchannel.AbstractHttpJspPagePortlet" - contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" - session="true" - import="it.eng.spago.base.*, - it.eng.spagobi.commons.constants.SpagoBIConstants" -%> -<%@page import="it.eng.spagobi.commons.utilities.ChannelUtilities"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.IMessageBuilder"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.UrlBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.IUrlBuilder"%> -<%@page import="it.eng.spago.base.SourceBean"%> -<%@page import="it.eng.spago.navigation.LightNavigationManager"%> -<%@page import="it.eng.spagobi.utilities.themes.ThemesManager"%> -<%@page import="it.eng.spagobi.commons.constants.ObjectsTreeConstants"%> -<%@page import="org.apache.commons.lang.StringEscapeUtils"%> -<%@page import="java.util.Enumeration"%> -<%@page import="java.util.Locale"%> -<%@include file="/WEB-INF/jsp/commons/angular/angularResource.jspf"%> - - <% - String strLocale = request.getParameter("locale"); - -%> - - - - - - - - - - " type="text/css" /> - - - ')"> - - - <% - String userDefaultValue =msgBuilder.getMessage("username",locale);// "Username"; - String pwdDefaultValue =msgBuilder.getMessage("password",locale);// "Password"; - %> -
-
-
-

<%=msgBuilder.getMessage("login",locale)%>

-
" method="POST" onsubmit="return escapeUserName()" class="reserved-area-form login"> -
-
- - -
-
- - -
-
- " /> -
-
- -
-
-
-
- - - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/signup/modify.jsp b/knowage/src/main/webapp/themes/geobi/jsp/signup/modify.jsp deleted file mode 100644 index fe2171f047d..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/signup/modify.jsp +++ /dev/null @@ -1,344 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@ page language="java" - extends="it.eng.spago.dispatching.httpchannel.AbstractHttpJspPagePortlet" - contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" - session="true" - import="it.eng.spago.base.*, - it.eng.spagobi.commons.constants.SpagoBIConstants, - it.eng.spagobi.commons.utilities.urls.IUrlBuilder, - it.eng.spagobi.commons.utilities.messages.IMessageBuilder" -%> -<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> -<%@page import="it.eng.spagobi.commons.utilities.ChannelUtilities"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.IMessageBuilder"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.UrlBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.IUrlBuilder"%> -<%@page import="it.eng.spago.base.SourceBean"%> -<%@page import="it.eng.spago.navigation.LightNavigationManager"%> -<%@page import="it.eng.spagobi.utilities.themes.ThemesManager"%> -<%@page import="it.eng.spagobi.commons.constants.ObjectsTreeConstants"%> -<%@page import="org.apache.commons.lang.StringEscapeUtils"%> -<%@page import="java.util.Enumeration"%> -<%@page import="java.util.List"%> -<%@page import="java.util.ArrayList"%> -<%@page import="java.util.Map"%> -<%@page import="java.util.HashMap"%> -<%@page import="it.eng.spagobi.community.mapping.SbiCommunity"%> - -<%@ include file="/WEB-INF/jsp/commons/portlet_base410.jsp"%> - - -<% - String defaultOrganization = msgBuilder.getMessage("profileattr.company",locale); - String defaultName = msgBuilder.getMessage("profileattr.firstname",locale); - String defaultSurname = msgBuilder.getMessage("profileattr.lastname",locale); - //String defaultUsername = msgBuilder.getMessage("username",locale); - //String defaultPassword = msgBuilder.getMessage("password",locale); - String defaultUsername = "Username"; - String defaultPassword = "Password"; - String defaultEmail = msgBuilder.getMessage("profileattr.email",locale); - String defaultConfirmPwd = msgBuilder.getMessage("confirmPwd",locale); - String confirmDelete = msgBuilder.getMessage("signup.msg.confirmDelete",locale); - - String msgConfirm = msgBuilder.getMessage( - "signup.msg.confirmDelete", locale); - String registrationSuccessMsg = msgBuilder.getMessage( - "signup.msg.modifySuccess", locale); - - Map data = (request.getAttribute("data")==null)?new HashMap():(Map)request.getAttribute("data"); - String myCommunity = (data.get("community")==null)?"":(String)data.get("community"); -%> - - - - - - - - - -
-
-
-

<%=msgBuilder.getMessage("modifyAccount",locale)%>

-
-
-
- - - -
-
- - -
-
- - -
-
- - -
- -
- - -
-
- - -
-
- " onclick="javascript:modify();"/> - - -

<%=msgBuilder.getMessage("deleteAccount",locale)%> <%=msgBuilder.getMessage("delete",locale)%>

-
-
-
-
-
-
-
- - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/signup/signup.jsp b/knowage/src/main/webapp/themes/geobi/jsp/signup/signup.jsp deleted file mode 100644 index fd842ce60b3..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/signup/signup.jsp +++ /dev/null @@ -1,275 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@ page language="java" - extends="it.eng.spago.dispatching.httpchannel.AbstractHttpJspPagePortlet" - contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8" - session="true" - import="it.eng.spago.base.*, - it.eng.spagobi.commons.constants.SpagoBIConstants, - it.eng.spagobi.commons.utilities.messages.IMessageBuilder" -%> -<%@page import="it.eng.spagobi.commons.utilities.ChannelUtilities"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.MessageBuilder"%> -<%@page import="it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.UrlBuilderFactory"%> -<%@page import="it.eng.spagobi.commons.utilities.urls.IUrlBuilder"%> -<%@page import="java.util.Locale"%> -<%@page import="it.eng.spago.base.SourceBean"%> -<%@page import="it.eng.spago.navigation.LightNavigationManager"%> -<%@page import="it.eng.spagobi.utilities.themes.ThemesManager"%> -<%@page import="it.eng.spagobi.commons.constants.ObjectsTreeConstants"%> -<%@page import="org.apache.commons.lang.StringEscapeUtils"%> -<%@page import="java.util.Enumeration"%> -<%@page import="java.util.List"%> -<%@page import="java.util.ArrayList"%> -<%@page import="it.eng.spagobi.community.mapping.SbiCommunity"%> - -<%@ include file="/WEB-INF/jsp/commons/portlet_base410.jsp"%> - -<% - String defaultOrganization = msgBuilder.getMessage("profileattr.company",request); - String defaultName = msgBuilder.getMessage("profileattr.firstname",request); - String defaultSurname = msgBuilder.getMessage("profileattr.lastname",request); - String defaultUsername = msgBuilder.getMessage("username",request); //"Username"; - String defaultPassword = msgBuilder.getMessage("password",request); //"Password"; - String defaultEmail = msgBuilder.getMessage("profileattr.email",request); - String defaultConfirmPwd = msgBuilder.getMessage("confirmPwd",request); - - String registrationSuccessMsg = msgBuilder.getMessage("signup.msg.success",request); - Locale localeSignup = (request.getAttribute("locale")==null)?null:(Locale)request.getAttribute("locale"); - - List communities = (request.getAttribute("communities")==null)?new ArrayList():(List)request.getAttribute("communities"); - -%> - - - - - - - - -
-
-
-

<%=msgBuilder.getMessage("registration",request)%>

-
" class="reserved-area-form"> -
-
- - - -
-
- - -
-
- - -
-
- - -
- -
- - -
-
- - -
- -
- " onclick="javascript:register();" /> -

<%=msgBuilder.getMessage("yesAccount",request)%> ">Login

-
-
-
-
-
-
- - - diff --git a/knowage/src/main/webapp/themes/geobi/jsp/userHome.jsp b/knowage/src/main/webapp/themes/geobi/jsp/userHome.jsp deleted file mode 100644 index 5ebd3b2eb31..00000000000 --- a/knowage/src/main/webapp/themes/geobi/jsp/userHome.jsp +++ /dev/null @@ -1,223 +0,0 @@ -<%-- -Knowage, Open Source Business Intelligence suite -Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - -Knowage is free software: you can redistribute it and/or modify -it under the terms of the GNU Affero General Public License as published by -the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - -Knowage 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 Affero General Public License for more details. - -You should have received a copy of the GNU Affero General Public License -along with this program. If not, see . ---%> - - -<%@page language="java" contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> -<%@ include file="/WEB-INF/jsp/wapp/homeBase.jsp"%> - - -<% - String mapsUrl="#"; - String datasetUrl = "#"; - String logoutUrl="#"; - String loginUrl="#"; - - Map langUrls = new HashMap(); - - for(int i=0; i< jsonMenuList.length(); i++){ - Object menuObj = jsonMenuList.get(i); - if(menuObj instanceof JSONObject) { - JSONObject menuItem = jsonMenuList.getJSONObject(i); - - if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("folder_open")){ - mapsUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("my_data")){ - datasetUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("power")){ - logoutUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("iconCls") && menuItem.getString("iconCls").equalsIgnoreCase("login")){ - loginUrl = menuItem.getString("href").replace("'","\\'"); - }else if(menuItem.has("itemLabel") && menuItem.getString("itemLabel") == "LANG"){ - List localesList = GeneralUtilities.getSupportedLocales(); - for (int j = 0; j < localesList.size() ; j++) { - String langUrl = "javascript:execUrl(\\'"+contextName+"/servlet/AdapterHTTP?ACTION_NAME=CHANGE_LANGUAGE&THEME_NAME="+currTheme; - Locale aLocale = (Locale)localesList.get(j); - langUrl += "&LANGUAGE_ID="+aLocale.getLanguage()+"&COUNTRY_ID="+aLocale.getCountry(); - langUrl += "\\')"; - langUrls.put( aLocale.getLanguage(), langUrl); - } - } - } - } -%> - - - - - - - - - - - - - diff --git a/knowage/src/main/webapp/themes/geobi/scripts/PIE_IE678.js b/knowage/src/main/webapp/themes/geobi/scripts/PIE_IE678.js deleted file mode 100644 index e12d37d0004..00000000000 --- a/knowage/src/main/webapp/themes/geobi/scripts/PIE_IE678.js +++ /dev/null @@ -1,72 +0,0 @@ -(function(O,H){var h=O.PIE||(O.PIE={});h.Fa=function(a){var b,d,e,c,g=arguments;b=1;for(d=g.length;b",d[0];);h.U=a;if(a===6)h.z=h.z.replace(/^-/,"");h.qa=H.documentMode||h.U;b.innerHTML='';a=b.firstChild;a.style.behavior="url(#default#VML)";h.tc=typeof a.adj==="object"})();(function(){var a=0,b={};h.Q={pa:function(d){return d&&d._pieId||(d._pieId="_"+a++)},Ac:function(d,e,c){var g=b[d],i,j;if(g)Object.prototype.toString.call(g)==="[object Array]"?g.push([e,c]):e.call(c,g);else{j=b[d]=[[e,c]]; -i=new Image;i.onload=function(){g=b[d]={f:i.width,e:i.height};for(var f=0,k=j.length;f=180?0:b,a<90||a>270?0:d);e=c[0];c=c[1];b=b-e;d=d-c;return{la:a, -qd:e,rd:c,ae:b,be:d,Jd:h.nb.ld(b,d,e,c)}},Od:function(a,b,d,e,c){if(d===0||d===180)return[a,c];else if(d===90||d===270)return[e,b];else{d=Math.tan((d-90)*Math.PI/180);a=d*a-b;b=-1/d;e=b*e-c;c=b-d;return[(e-a)/c,(d*e-b*a)/c]}},ld:function(a,b,d,e){a=d-a;b=e-b;return Math.abs(a===0?b:b===0?a:Math.sqrt(a*a+b*b))}};h.ja=function(){this.Eb=[];this.hc={}};h.ja.prototype={ca:function(a){var b=h.Q.pa(a),d=this.hc,e=this.Eb;if(!(b in d)){d[b]=e.length;e.push(a)}},Ka:function(a){a=h.Q.pa(a);var b=this.hc;if(a&& -a in b){delete this.Eb[b[a]];delete b[a]}},Da:function(){for(var a=this.Eb,b=a.length;b--;)a[b]&&a[b]()}};h.Pa=new h.ja;h.Pa.Ud=function(){var a=this,b;if(!a.Vd){b=H.documentElement.currentStyle.getAttribute(h.z+"poll-interval")||250;(function d(){a.Da();setTimeout(d,b)})();a.Vd=1}};(function(){function a(){h.J.Da();O.detachEvent("onunload",a);O.PIE=null}h.J=new h.ja;O.attachEvent("onunload",a);h.J.za=function(b,d,e){b.attachEvent(d,e);this.ca(function(){b.detachEvent(d,e)})}})();h.Sa=new h.ja;h.J.za(O, -"onresize",function(){h.Sa.Da()});(function(){function a(){h.pb.Da()}h.pb=new h.ja;h.J.za(O,"onscroll",a);h.Sa.ca(a)})();(function(){function a(){d=h.mb.kd()}function b(){if(d){for(var e=0,c=d.length;e0)return parseFloat(k);else if(f.tagName in h.Tb){m=this;l=f.parentNode;return h.m(k).a(l,function(){return m.yb(l)})}else{f.appendChild(b);k=b.offsetWidth;b.parentNode===f&&f.removeChild(b);return k}}};a.gb=function(f){return f/c.pt};h.m=function(f){return j[f]||(j[f]=new a(f))};return a}();h.kb=function(){function a(c){this.ga=c}var b=h.m("50%"), -d={top:1,center:1,bottom:1},e={left:1,center:1,right:1};a.prototype={Bd:function(){if(!this.Rb){var c=this.ga,g=c.length,i=h.q,j=i.ya,f=h.m("0");j=j.W;f=["left",f,"top",f];if(g===1){c.push(new i.rb(j,"center"));g++}if(g===2){j&(c[0].h|c[1].h)&&c[0].c in d&&c[1].c in e&&c.push(c.shift());if(c[0].h&j)if(c[0].c==="center")f[1]=b;else f[0]=c[0].c;else if(c[0].G())f[1]=h.m(c[0].c);if(c[1].h&j)if(c[1].c==="center")f[3]=b;else f[2]=c[1].c;else if(c[1].G())f[3]=h.m(c[1].c)}this.Rb=f}return this.Rb},coords:function(c, -g,i){var j=this.Bd(),f=j[1].a(c,g);c=j[3].a(c,i);return{x:j[0]==="right"?g-f:f,y:j[2]==="bottom"?i-c:c}}};return a}();h.Ma=function(){function a(b,d){this.f=b;this.e=d}a.prototype={a:function(b,d,e,c,g){var i=this.f,j=this.e,f=d/e;c=c/g;if(i==="contain"){i=c>f?d:e*c;j=c>f?d/c:e}else if(i==="cover"){i=c1)l-=1;return 255*(6*l<1?f+(k-f)*l*6:2*l<1?k:3*l<2?f+(k-f)*(2/3-l)*6:f)}function b(f){this.ha=f}var d={};b.Td=/\s*rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(,\s*(\d+|\d*\.\d+))?\s*\)\s*/; -b.Fd=/\s*hsla?\(\s*(\d*\.?\d+)\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*(,\s*(\d+|\d*\.\d+))?\s*\)\s*/;b.db={};for(var e="black|0|navy|3k|darkblue|b|mediumblue|1u|blue|1e|darkgreen|jk1|green|5j4|teal|3k|darkcyan|26j|deepskyblue|ad0|darkturquoise|2xe|mediumspringgreen|8nd|lime|va|springgreen|3j|aqua|3k|cyan|0|midnightblue|xunl|dodgerblue|7ogf|lightseagreen|2zsb|forestgreen|2lbs|seagreen|guut|darkslategray|12pk|limegreen|4wkj|mediumseagreen|dwlb|turquoise|5v8f|royalblue|r2p|steelblue|75qr|darkslateblue|2fh3|mediumturquoise|ta9|indigo|32d2|darkolivegreen|emr1|cadetblue|ebu9|cornflowerblue|6z4d|mediumaquamarine|3459|dimgray|3nwf|slateblue|1bok|olivedrab|1opi|slategray|6y5p|lightslategray|9vk9|mediumslateblue|5g0l|lawngreen|27ma|chartreuse|48ao|aquamarine|5w|maroon|18|purple|3k|olive|p6o|gray|3k|lightslateblue|5j7j|skyblue|4q98|lightskyblue|f|blueviolet|3bhk|darkred|15we|darkmagenta|3v|saddlebrown|djc|darkseagreen|69vg|lightgreen|1og1|mediumpurple|3ivc|darkviolet|sfv|palegreen|6zt1|darkorchid|awk|yellowgreen|292e|sienna|7r3v|brown|6sxp|darkgray|6bgf|lightblue|5vlp|greenyellow|7k9|paleturquoise|2pxb|lightsteelblue|169c|powderblue|5jc|firebrick|1rgc|darkgoldenrod|8z55|mediumorchid|2jm0|rosybrown|34jg|darkkhaki|1mfw|silver|49jp|mediumvioletred|8w5h|indianred|8tef|peru|82r|violetred|3ntd|feldspar|212d|chocolate|16eh|tan|ewe|lightgrey|1kqv|palevioletred|6h8g|metle|fnp|orchid|2dj2|goldenrod|abu|crimson|20ik|gainsboro|13mo|plum|12pt|burlywood|1j8q|lightcyan|3794|lavender|8agr|darksalmon|3rsw|violet|6wz8|palegoldenrod|k3g|lightcoral|28k6|khaki|k5o|aliceblue|3n7|honeydew|1dd|azure|f|sandybrown|5469|wheat|1q37|beige|4kp|whitesmoke|p|mintcream|1z9|ghostwhite|46bp|salmon|25bn|antiquewhite|l7p|linen|zz|lightgoldenrodyellow|1yk|oldlace|46qc|red|1gka|magenta|73|fuchsia|0|deeppink|3v8|orangered|9kd|tomato|5zb|hotpink|19p|coral|49o|darkorange|2i8|lightsalmon|41m|orange|w6|lightpink|3i9|pink|1ze|gold|4dx|peachpuff|qh|navajowhite|s4|moccasin|16w|bisque|f|mistyrose|t|blanchedalmond|1d8|papayawhip|so|lavenderblush|80|seashell|zd|cornsilk|ku|lemonchiffon|dt|floralwhite|z|snow|a|yellow|sm|lightyellow|68|ivory|g|white|f".split("|"), -c=0,g=e.length,i=0,j;c=this.$a.length)return c();i=this.ch;g=this.$a.substring(this.ch);j=g.charAt(0);switch(j){case "#":if(f=g.match(this.Dd)){this.ch+=f[0].length;return e(b.u,f[0])}break;case '"':case "'":if(f=g.match(this.ce)){this.ch+=f[0].length;return e(b.Nc, -f[2]||f[3]||"")}break;case "/":case ",":this.ch++;return e(b.xa,j);case "u":if(f=g.match(this.url)){this.ch+=f[0].length;return e(b.URL,f[2]||f[3]||f[4]||"")}}if(f=g.match(this.Nd)){j=f[0];this.ch+=j.length;if(g.charAt(j.length)==="%"){this.ch++;return e(b.Ta,j+"%")}if(f=g.substring(j.length).match(this.gc)){j+=f[0];this.ch+=f[0].length;return e(this.ie[f[0].toLowerCase()]||b.Kc,j)}return e(b.wa,j)}if(f=g.match(this.gc)){j=f[0];this.ch+=j.length;if(j.toLowerCase()in h.Ic.db||j==="currentColor"||j=== -"transparent")return e(b.u,j);if(g.charAt(j.length)==="("){this.ch++;if(j.toLowerCase()in this.cd){g=function(o){return o&&o.h&b.wa};f=function(o){return o&&o.h&(b.wa|b.Ta)};var l=function(o,s){return o&&o.c===s},m=function(){return k.next(1)};if((j.charAt(0)==="r"?f(m()):g(m()))&&l(m(),",")&&f(m())&&l(m(),",")&&f(m())&&(j==="rgb"||j==="hsa"||l(m(),",")&&g(m()))&&l(m(),")"))return e(b.u,this.$a.substring(i,this.ch));return c()}return e(b.Mb,j)}return e(b.W,j)}this.ch++;return e(b.Lb,j)},C:function(){return this.ga[this.Ja-- - -2]},all:function(){for(;this.next(););return this.ga},va:function(d,e){for(var c=[],g,i;g=this.next();){if(d(g)){i=true;this.C();break}c.push(g)}return e&&!i?null:c}};return a}();h.Kb=function(a){this.d=a};h.Kb.prototype={X:0,oc:function(){var a=this.ub,b;return!a||(b=this.n())&&(a.x!==b.x||a.y!==b.y)},Yd:function(){var a=this.ub,b;return!a||(b=this.n())&&(a.f!==b.f||a.e!==b.e)},cc:function(){var a=this.d,b=a.getBoundingClientRect(),d=h.qa===9,e=h.U===7,c=b.right-b.left;return{x:b.left,y:b.top,f:d|| -e?a.offsetWidth:c,e:d||e?a.offsetHeight:b.bottom-b.top,jc:e&&c?a.offsetWidth/c:1}},n:function(){return this.X?this.Va||(this.Va=this.cc()):this.cc()},Cd:function(){return!!this.ub},cb:function(){++this.X},ib:function(){if(!--this.X){if(this.Va)this.ub=this.Va;this.Va=null}}};(function(){function a(b){var d=h.Q.pa(b);return function(){if(this.X){var e=this.Pb||(this.Pb={});return d in e?e[d]:(e[d]=b.call(this))}else return b.call(this)}}h.p={X:0,ba:function(b){function d(e){this.d=e;this.Ob=this.T()} -h.Fa(d.prototype,h.p,b);d.Vc={};return d},i:function(){var b=this.T(),d=this.constructor.Vc;return b?b in d?d[b]:(d[b]=this.ea(b)):null},T:a(function(){var b=this.d,d=this.constructor,e=b.style;b=b.currentStyle;var c=this.Aa,g=this.Ia,i=d.Tc||(d.Tc=h.z+c);d=d.Uc||(d.Uc=h.qb+g.charAt(0).toUpperCase()+g.substring(1));return e[d]||b.getAttribute(i)||e[g]||b.getAttribute(c)}),j:a(function(){return!!this.i()}),L:a(function(){var b=this.T(),d=b!==this.Ob;this.Ob=b;return d}),oa:a,cb:function(){++this.X}, -ib:function(){--this.X||delete this.Pb}}})();h.Hb=h.p.ba({Aa:h.z+"background",Ia:h.qb+"Background",Yc:{scroll:1,fixed:1,local:1},hb:{"repeat-x":1,"repeat-y":1,repeat:1,"no-repeat":1},nc:{"padding-box":1,"border-box":1,"content-box":1},Qd:{top:1,right:1,bottom:1,left:1,center:1},Zd:{contain:1,cover:1},fe:{top:1,bottom:1},Kd:{left:1,right:1},fb:{Oa:"backgroundClip",u:"backgroundColor",ia:"backgroundImage",Ra:"backgroundOrigin",P:"backgroundPosition",ka:"backgroundRepeat",Ua:"backgroundSize"},ea:function(a){function b(r){return r&& -(r.G()&&h.m(r.c)||r.c==="auto"&&"auto")}var d=this.d.currentStyle,e,c,g,i=h.q.ya,j=i.xa,f=i.W,k=i.u,l,m,o=0,s=this.Qd,q,t,n,u,p={R:[]};if(this.xb()){e=new h.q(a);for(g={};c=e.next();){l=c.h;m=c.c;if(!g.V&&l&i.Mb&&m==="linear-gradient"){q={ua:[],V:m};for(t={};c=e.next();){l=c.h;m=c.c;if(l&i.Lb&&m===")"){t.color&&q.ua.push(t);q.ua.length>1&&h.Fa(g,q);break}if(l&k){if(q.la||q.ab){c=e.C();if(c.h!==j)break;e.next()}t={color:h.aa(m)};c=e.next();if(c.G())t.lc=h.m(c.c);else e.C()}else if(l&i.La&&!q.la&&!q.ab&& -!t.color&&!q.ua.length)q.la=new h.Cc(c.c);else if(l&i.W&&m==="to"&&!q.ab&&!q.la&&!t.color&&!q.ua.length){n=this.fe;u=this.Kd;c=e.va(function(r){return!(r&&r.h&i.W&&(r.c in n||r.c in u))});l=c.length;c=[c[0]&&c[0].c,c[1]&&c[1].c];if(l<1||l>2||l>1&&(c[0]in n&&c[1]in n||c[0]in u&&c[1]in u))break;q.ab=c}else if(l&j&&m===","){if(t.color){q.ua.push(t);t={}}}else break}}else if(!g.V&&l&i.URL){g.Cb=m;g.V="image"}else if((c&&c.G()||c.h&f&&c.c in s)&&!g.ma){e.C();g.ma=new h.kb(e.va(function(r){return!(r&&r.G()|| -r.h&f&&r.c in s)},false))}else if(l&f)if(m in this.hb&&!g.bb)g.bb=m;else if(m in this.nc&&!g.Ya){g.Ya=m;if((c=e.next())&&c.h&f&&c.c in this.nc)g.Xa=c.c;else{g.Xa=m;e.C()}}else if(m in this.Yc&&!g.$c)g.$c=m;else return null;else if(l&k&&!p.color)p.color=h.aa(m);else if(l&j&&m==="/"&&!g.Za&&g.ma){c=e.next();if(c.h&f&&c.c in this.Zd)g.Za=new h.Ma(c.c);else if(q=b(c)){t=b(e.next());if(!t){t=q;e.C()}g.Za=new h.Ma(q,t)}else return null}else if(l&j&&m===","&&g.V){g.mc=a.substring(o,e.ch-1);o=e.ch;p.R.push(g); -g={}}else return null}if(g.V){g.mc=a.substring(o);p.R.push(g)}p.bd=g.Xa}else this.yc(h.qa<9?function(){var r=this.fb,v=d[r.P+"X"],C=d[r.P+"Y"],y=d[r.ia],B=d[r.u];if(B!=="transparent")p.color=h.aa(B);if(y!=="none")p.R=[{V:"image",Cb:(new h.q(y)).next().c,bb:d[r.ka],ma:new h.kb((new h.q(v+" "+C)).all())}]}:function(){var r=this.fb,v=/\s*,\s*/,C=d[r.ia].split(v),y=d[r.u],B,F,G,K,J,w;if(y!=="transparent")p.color=h.aa(y);if((K=C.length)&&C[0]!=="none"){y=d[r.ka].split(v);B=d[r.P].split(v);F=d[r.Ra].split(v); -G=d[r.Oa].split(v);r=d[r.Ua].split(v);p.R=[];for(v=0;v8,d=this.fb,e=this.d.runtimeStyle,c=e[d.ia],g=e[d.u],i=e[d.ka],j,f,k,l;if(c)e[d.ia]="";if(g)e[d.u]="";if(i)e[d.ka]="";if(b){j=e[d.Oa];f=e[d.Ra];l=e[d.P];k= -e[d.Ua];if(j)e[d.Oa]="";if(f)e[d.Ra]="";if(l)e[d.P]="";if(k)e[d.Ua]=""}a=a.call(this);if(c)e[d.ia]=c;if(g)e[d.u]=g;if(i)e[d.ka]=i;if(b){if(j)e[d.Oa]=j;if(f)e[d.Ra]=f;if(l)e[d.P]=l;if(k)e[d.Ua]=k}return a},T:h.p.oa(function(){return this.xb()||this.yc(function(){var a=this.d.currentStyle,b=this.fb;return a[b.u]+" "+a[b.ia]+" "+a[b.ka]+" "+a[b.P+"X"]+" "+a[b.P+"Y"]})}),xb:h.p.oa(function(){var a=this.d;return a.style[this.Ia]||a.currentStyle.getAttribute(this.Aa)}),ud:function(a,b,d,e){var c=this.d, -g=b.n();b=g.f;g=g.e;if(a!=="border-box")if((d=d.i())&&(d=d.O)){b-=d.l.a(c)+d.l.a(c);g-=d.t.a(c)+d.b.a(c)}if(a==="content-box")if(a=e.i()){b-=a.l.a(c)+a.l.a(c);g-=a.t.a(c)+a.b.a(c)}return{f:b,e:g}},ic:function(){var a=0;if(h.U<7){a=this.d;a=""+(a.style[h.qb+"PngFix"]||a.currentStyle.getAttribute(h.z+"png-fix"))==="true"}return a},j:h.p.oa(function(){return(this.xb()||this.ic())&&!!this.i()})});h.Jb=h.p.ba({sc:["Top","Right","Bottom","Left"],Ld:{thin:"1px",medium:"3px",thick:"5px"},ea:function(){var a= -{},b={},d={},e=false,c=true,g=true,i=true;this.zc(function(){for(var j=this.d.currentStyle,f=0,k,l,m,o,s,q,t;f<4;f++){m=this.sc[f];t=m.charAt(0).toLowerCase();k=b[t]=j["border"+m+"Style"];l=j["border"+m+"Color"];m=j["border"+m+"Width"];if(f>0){if(k!==o)g=false;if(l!==s)c=false;if(m!==q)i=false}o=k;s=l;q=m;d[t]=h.aa(l);m=a[t]=h.m(b[t]==="none"?"0":this.Ld[m]||m);if(m.a(this.d)>0)e=true}});return e?{O:a,de:b,dd:d,qe:i,ed:c,ee:g}:null},T:h.p.oa(function(){var a=this.d,b=a.currentStyle,d;a.tagName in -h.uc&&a.offsetParent.currentStyle.borderCollapse==="collapse"||this.zc(function(){d=b.borderWidth+"|"+b.borderStyle+"|"+b.borderColor});return d}),zc:function(a){var b=this.d.runtimeStyle,d=b.borderWidth,e=b.borderColor;if(d)b.borderWidth="";if(e)b.borderColor="";a=a.call(this);if(d)b.borderWidth=d;if(e)b.borderColor=e;return a}});(function(){h.lb=h.p.ba({Aa:"border-radius",Ia:"borderRadius",ea:function(b){var d=null,e,c,g,i,j=false;if(b){c=new h.q(b);var f=function(){for(var k=[],l;(g=c.next())&& -g.G();){i=h.m(g.c);l=i.dc();if(l<0)return null;if(l>0)j=true;k.push(i)}return k.length>0&&k.length<5?{tl:k[0],tr:k[1]||k[0],br:k[2]||k[0],bl:k[3]||k[1]||k[0]}:null};if(b=f()){if(g){if(g.h&h.q.ya.xa&&g.c==="/")e=f()}else e=b;if(j&&b&&e)d={x:b,y:e}}}return d}});var a=h.m("0");a={tl:a,tr:a,br:a,bl:a};h.lb.Bc={x:a,y:a}})();h.Ib=h.p.ba({Aa:"border-image",Ia:"borderImage",hb:{stretch:1,round:1,repeat:1,space:1},ea:function(a){var b=null,d,e,c,g,i,j,f=0,k=h.q.ya,l=k.W,m=k.wa,o=k.Ta;if(a){d=new h.q(a);b= -{};for(var s=function(n){return n&&n.h&k.xa&&n.c==="/"},q=function(n){return n&&n.h&l&&n.c==="fill"},t=function(){g=d.va(function(n){return!(n.h&(m|o))});if(q(d.next())&&!b.fill)b.fill=true;else d.C();if(s(d.next())){f++;i=d.va(function(n){return!n.G()&&!(n.h&l&&n.c==="auto")});if(s(d.next())){f++;j=d.va(function(n){return!n.Ea()})}}else d.C()};a=d.next();){e=a.h;c=a.c;if(e&(m|o)&&!g){d.C();t()}else if(q(a)&&!b.fill){b.fill=true;t()}else if(e&l&&this.hb[c]&&!b.repeat){b.repeat={e:c};if(a=d.next())if(a.h& -l&&this.hb[a.c])b.repeat.wc=a.c;else d.C()}else if(e&k.URL&&!b.src)b.src=c;else return null}if(!b.src||!g||g.length<1||g.length>4||i&&i.length>4||f===1&&i.length<1||j&&j.length>4||f===2&&j.length<1)return null;if(!b.repeat)b.repeat={e:"stretch"};if(!b.repeat.wc)b.repeat.wc=b.repeat.e;a=function(n,u){return{t:u(n[0]),r:u(n[1]||n[0]),b:u(n[2]||n[0]),l:u(n[3]||n[1]||n[0])}};b.slice=a(g,function(n){return h.m(n.h&m?n.c+"px":n.c)});if(i&&i[0])b.O=a(i,function(n){return n.G()?h.m(n.c):n.c});if(j&&j[0])b.Ga= -a(j,function(n){return n.Ea()?h.m(n.c):n.c})}return b}});h.Hc=h.p.ba({Aa:"box-shadow",Ia:"boxShadow",ea:function(a){var b,d=h.m,e=h.q.ya,c;if(a){c=new h.q(a);b={Ga:[],Db:[]};for(a=function(){for(var g,i,j,f,k,l;g=c.next();){j=g.c;i=g.h;if(i&e.xa&&j===",")break;else if(g.Ea()&&!k){c.C();k=c.va(function(m){return!m.Ea()})}else if(i&e.u&&!f)f=j;else if(i&e.W&&j==="inset"&&!l)l=true;else return false}g=k&&k.length;if(g>1&&g<5){(l?b.Db:b.Ga).push({ke:d(k[0].c),le:d(k[1].c),blur:d(k[2]?k[2].c:"0"),$d:d(k[3]? -k[3].c:"0"),color:h.aa(f||"currentColor")});return true}return false};a(););}return b&&(b.Db.length||b.Ga.length)?b:null}});h.Nb=h.p.ba({ea:function(a){a=new h.q(a);for(var b=[],d;(d=a.next())&&d.G();)b.push(h.m(d.c));return b.length>0&&b.length<5?{t:b[0],r:b[1]||b[0],b:b[2]||b[0],l:b[3]||b[1]||b[0]}:null},T:h.p.oa(function(){var a=this.d,b=a.runtimeStyle,d=b.padding;if(d)b.padding="";a=a.currentStyle.padding;if(d)b.padding=d;return a})});h.Oc=h.p.ba({T:h.p.oa(function(){var a=this.d,b=a.runtimeStyle, -d=a.currentStyle;a=b.visibility;b.visibility="";d=d.visibility+"|"+d.display;b.visibility=a;return d}),ea:function(){var a=this.T().split("|");return{xc:a[0]!=="hidden",Vb:a[1]!=="none"}},j:function(){return false}});h.Pc=function(){function a(c){return function(){var g=arguments,i,j=g.length,f,k,l;f=this[d+c]||(this[d+c]={});for(i=0;i';j.kc=1;i=[k,f,' id="',j.Xb,'" style="',j.Ad(),'" ',j.gd];c(j[d]);i.push(">");g("fill");i.push("");return i.join("")},k:function(){var c=this.B(),g=c&&c.parentNode;if(g){g.removeChild(c);delete this.Qb}}};return b}();h.v={sa:function(a){function b(d,e,c,g){this.d=d;this.o=e;this.g=c;this.parent=g}h.Fa(b.prototype,h.v,a);return b},ra:function(){return false},qc:h.pd,Gb:function(){this.j()?this.Ca():this.k()}, -Bb:function(){this.d.runtimeStyle.borderColor="transparent"},k:function(){}};h.Fa(h.v,{B:function(a,b){var d=this.wb||(this.wb={}),e=d[a];if(!e){e=d[a]=new h.Pc(a,b);this.parent.sd(e)}return e},Ba:function(a){var b=this.wb,d=b&&b[a];if(d){d.k();this.parent.Sd(d);delete b[a]}return!!d},zd:function(a){var b=this.d,d=this.o.n(),e=d.f,c=d.e,g,i,j,f,k,l;d=a.x.tl.a(b,e);g=a.y.tl.a(b,c);i=a.x.tr.a(b,e);j=a.y.tr.a(b,c);f=a.x.br.a(b,e);k=a.y.br.a(b,c);l=a.x.bl.a(b,e);a=a.y.bl.a(b,c);e=Math.min(e/(d+i),c/(j+ -k),e/(l+f),c/(g+a));if(e<1){d*=e;g*=e;i*=e;j*=e;f*=e;k*=e;l*=e;a*=e}return{x:{tl:d,tr:i,br:f,bl:l},y:{tl:g,tr:j,br:k,bl:a}}},Z:function(a,b,d,e,c,g){a=this.$(a,b,d,e,c,g);return"m"+a[0]+","+a[1]+"qy"+a[2]+","+a[3]+"l"+a[4]+","+a[5]+"qx"+a[6]+","+a[7]+"l"+a[8]+","+a[9]+"qy"+a[10]+","+a[11]+"l"+a[12]+","+a[13]+"qx"+a[14]+","+a[15]+"x"},$:function(a,b,d,e,c,g){var i=this.o.n(),j=i.f*c,f=i.e*c,k=Math;i=k.floor;var l=k.ceil,m=k.max;k=k.min;a*=c;b*=c;d*=c;e*=c;g||(g=this.g.F.i());if(g){g=this.zd(g);var o= -g.x.tl*c,s=g.y.tl*c,q=g.x.tr*c,t=g.y.tr*c,n=g.x.br*c,u=g.y.br*c,p=g.x.bl*c;c=g.y.bl*c;e=[i(e),i(k(m(s,a),f-d)),i(k(m(o,e),j-b)),i(a),l(m(e,j-m(q,b))),i(a),l(j-b),i(k(m(t,a),f-d)),l(j-b),l(m(a,f-m(u,d))),l(m(e,j-m(n,b))),l(f-d),i(k(m(p,e),j-b)),l(f-d),i(e),l(m(a,f-m(c,d)))]}else{a=i(a);b=l(j-b);d=l(f-d);e=i(e);e=[e,a,e,a,b,a,b,a,b,d,b,d,e,d,e,d]}return e},Bb:function(){var a=this.d,b=a.currentStyle,d=a.runtimeStyle,e=a.tagName,c=h.U===6,g;if(c&&(e in h.Tb||e==="FIELDSET")||e==="BUTTON"||e==="INPUT"&& -a.type in h.Hd){d.borderWidth="";e=this.g.s.sc;for(g=e.length;g--;){c=e[g];d["padding"+c]="";d["padding"+c]=h.m(b["padding"+c]).a(a)+h.m(b["border"+c+"Width"]).a(a)+(h.U!==8&&g%2?1:0)}d.borderWidth=0}else if(c){if(a.childNodes.length!==1||a.firstChild.tagName!=="ie6-mask"){b=H.createElement("ie6-mask");e=b.style;e.visibility="visible";for(e.zoom=1;e=a.firstChild;)b.appendChild(e);a.appendChild(b);d.visibility="hidden"}}else d.borderColor="transparent"},pe:function(){},k:function(){var a=this.wb,b; -if(a)for(b in a)a.hasOwnProperty(b)&&this.Ba(b)}});h.Mc=h.v.sa({j:function(){var a=this.ad;for(var b in a)if(a.hasOwnProperty(b)&&a[b].j())return true;return false},ac:function(){var a=this.ec(),b=a,d;a=a.currentStyle;var e=a.position,c=0,g=0;g=this.o.n();var i=this.g.jb.i(),j=g.jc;if(e==="fixed"&&h.U>6){c=g.x*j;g=g.y*j;b=e}else{do b=b.offsetParent;while(b&&b.currentStyle.position==="static");if(b){d=b.getBoundingClientRect();b=b.currentStyle;c=(g.x-d.left)*j-(parseFloat(b.borderLeftWidth)||0);g= -(g.y-d.top)*j-(parseFloat(b.borderTopWidth)||0)}else{b=H.documentElement;c=(g.x+b.scrollLeft-b.clientLeft)*j;g=(g.y+b.scrollTop-b.clientTop)*j}b="absolute"}return"direction:ltr;position:absolute;behavior:none !important;position:"+b+";left:"+c+"px;top:"+g+"px;z-index:"+(e==="static"?-1:a.zIndex)+";display:"+(i.xc&&i.Vb?"block":"none")},vc:function(){var a=this.bc();if(a&&(this.o.oc()||this.g.jb.L()))a.style.cssText=this.ac()},ec:function(){var a=this.d;return a.tagName in h.uc?a.offsetParent:a},bc:function(){var a= -this.sb;if(!a)a=this.sb=H.getElementById("_pie"+h.Q.pa(this));return a},Gb:function(){var a=this.Wa,b,d,e,c,g,i;if(this.j())if(a)if(b=this.vb){d=0;for(e=a.length;d'];d=0;for(e=a.length;d");this.ec().insertAdjacentHTML("beforeBegin",b.join(""));this.vb=a;this.Wa=0}}else this.vc();else this.k()},Wd:function(a,b){return a.eb-b.eb},sd:function(a){(this.Wa||(this.Wa=[])).push(a)},Sd:function(a){var b=this.vb,d;if(b)for(d=b.length;d--;)if(b[d]===a){b.splice(d,1);break}},k:function(){var a=this.sb,b;if(a&&(b=a.parentNode))b.removeChild(a);delete this.sb;delete this.vb}});H.createElement("css3pie");h.Dc=h.v.sa({H:2,ra:function(){var a=this.g;return a.K.L()||a.F.L()},j:function(){var a= -this.g;return a.D.j()||a.F.j()||a.K.j()||a.na.j()&&a.na.i().Db},Ca:function(){var a=this.o.n();if(a.f&&a.e){this.nd();this.od()}},nd:function(){var a=this.g.K.i(),b=this.o.n(),d=this.d,e=a&&a.color,c;if(e&&e.Y()>0){this.fc();c=this.B("bgColor",this.H);c.ta(b.f,b.e);c.fa("path",this.$b(b,a.bd));c.w("color",e.M(d));a=e.Y();a<1&&c.w("opacity",a)}else this.Ba("bgColor")},od:function(){var a=this.g.K.i(),b=this.o.n();a=a&&a.R;var d,e,c,g,i;if(a){this.fc();c=b.f;g=b.e;for(i=a.length;i--;){d=a[i];e=this.B("bgImage"+ -i,this.H+(0.5-i/1E3));e.fa("path",this.$b(b,d.Xa));e.ta(c,g);if(d.V==="linear-gradient")this.Xc(e,d);else{e.w("type","tile","color","none");this.Pd(e,d.Cb,i)}}}for(i=a?a.length:0;this.Ba("bgImage"+i++););},Pd:function(a,b,d){h.Q.Ac(b,function(e){var c=this.d,g=this.o.n(),i=g.f,j=g.e;if(i&&j){var f=this.g,k=f.K,l=k.i().R[d],m=k.ud(l.Ya,this.o,f.s,f.da);f=(l.Za||h.Ma.Jc).a(this.d,m.f,m.e,e.f,e.e);k=this.vd(l.Ya);c=l.ma?l.ma.coords(c,m.f-f.f,m.e-f.e):{x:0,y:0};l=l.bb;var o=0,s=0,q=i+1,t=j+1,n=h.U=== -8?0:1;m=Math.round(k.x+c.x)+0.5;k=Math.round(k.y+c.y)+0.5;a.w("src",b,"position",m/i+","+k/j,"size",f.f!==e.f||f.e!==e.e||g.jc!==1||screen.logicalXDPI/screen.deviceXDPI!==1?h.Qa.gb(f.f)+"pt,"+h.Qa.gb(f.e)+"pt":"");if(l&&l!=="repeat"){if(l==="repeat-x"||l==="no-repeat"){o=k+1;t=k+f.e+n}if(l==="repeat-y"||l==="no-repeat"){s=m+1;q=m+f.f+n}a.Ha("clip","rect("+o+"px,"+q+"px,"+t+"px,"+s+"px)")}}},this)},$b:function(a,b){var d=0,e=0,c=0,g=0,i=this.d,j=this.g,f;if(b&&b!=="border-box")if((f=j.s.i())&&(f=f.O)){d+= -f.t.a(i);e+=f.r.a(i);c+=f.b.a(i);g+=f.l.a(i)}if(b==="content-box")if(b=j.da.i()){d+=b.t.a(i);e+=b.r.a(i);c+=b.b.a(i);g+=b.l.a(i)}return"m0,0r0,0m"+a.f*2+","+a.e*2+"r0,0"+this.Z(d,e,c,g,2)},vd:function(a){var b=this.d,d=this.g,e=0,c=0,g;if(a!=="border-box")if((g=d.s.i())&&(g=g.O)){e+=g.l.a(b);c+=g.t.a(b)}if(a==="content-box")if(a=d.da.i()){e+=a.l.a(b);c+=a.t.a(b)}return{x:e,y:c}},Xc:function(a,b){var d=this.d,e=this.o.n(),c=e.f,g=e.e;e=b.ua;var i=e.length,j=Math.PI,f=h.nb.xd(d,c,g,b),k=f.la;b=f.Jd; -var l,m;for(c=k%90?Math.atan2(f.be-f.rd,(f.qd-f.ae)*c/g)/j*180-90:-k;c<0;)c+=360;c%=360;g=[];j=[];for(f=0;f0){k[0]=this.Z(0,0,0,0,2);p=a.t;if(p==="double")k.push(this.Z(j/3,l/3,m/3,g/3,2)+this.Z(j*2/3,l*2/3,m*2/3,g*2/3,2));else if(p in u){c=this.$(j,l,m,g,2);this.S(k,c[2],c[4],j*2,0,0,a.t);this.S(k,c[7], -c[9],l*2,(e.f-l)*2,1,a.r);this.S(k,c[12],c[10],m*2,(e.e-m)*2,0,a.b);this.S(k,c[1],c[15],g*2,0,1,a.l)}k.push(this.Z(j,l,m,g,2));b.push(k.join(""),i.t.M(d))}}else{o=this.$(0,0,0,0,2);c=this.$(j,l,m,g,2);for(n in t)if(t.hasOwnProperty(n)&&i[n].Y()>0){p=t[n];var v=p[0],C=p[1],y=p[2],B=p[3],F=p[4],G=p[5],K=p[6],J=p[7],w=p[8],P=n==="t"||n==="l";p=a[n];k[0]="al"+o[v]+","+o[C]+","+f(o[y]-o[v])+","+f(o[B]-o[C])+","+(w+45)*65535+",-2949075ae"+o[F]+","+o[G]+","+f(o[K]-o[F])+","+f(o[J]-o[G])+","+w*65535+",-2949075"; -if(p in this.md){if(!s)if(p==="double"){s=this.$(j/3,l/3,m/3,g/3,2);q=this.$(j*2/3,l*2/3,m*2/3,g*2/3,2)}else s=q=this.$(j/2,l/2,m/2,g/2,2);k.push("ae"+s[F]+","+s[G]+","+f(s[K]-s[F])+","+f(s[J]-s[G])+","+(w-45)*65535+",2949075ae"+s[v]+","+s[C]+","+f(s[y]-s[v])+","+f(s[B]-s[C])+","+w*65535+",2949075x");if(p!=="double"){r=i[n].M(d)+((p==="groove"?P:!P)?" darken(128)":" lighten(128)");b.push(k.join(""),r);k.length=0}k.push("al"+q[v]+","+q[C]+","+f(q[y]-q[v])+","+f(q[B]-q[C])+","+(w+45)*65535+",-2949075ae"+ -q[F]+","+q[G]+","+f(q[K]-q[F])+","+f(q[J]-q[G])+","+w*65535+",-2949075")}k.push("ae"+c[F]+","+c[G]+","+f(c[K]-c[F])+","+f(c[J]-c[G])+","+(w-45)*65535+",2949075ae"+c[v]+","+c[C]+","+f(c[y]-c[v])+","+f(c[B]-c[C])+","+w*65535+",2949075x");if(p in u)n==="t"?this.S(k,c[2],c[4],j*2,0,0,p):n==="r"?this.S(k,c[7],c[9],l*2,(e.f-l)*2,1,p):n==="b"?this.S(k,c[12],c[10],m*2,(e.e-m)*2,0,p):this.S(k,c[1],c[15],g*2,0,1,p);r=i[n].M(d);if(p in this.Ub)r+=(p==="groove"||p==="outset"?P:!P)?" lighten(128)":" darken(128)"; -b.push(k.join(""),r);k.length=0}}}return b},k:function(){if(this.Yb||!this.g.D.j())this.d.runtimeStyle.borderColor="";h.v.k.call(this)}});h.Ec=h.v.sa({H:5,ra:function(){return this.g.D.L()},j:function(){return this.g.D.j()},Ca:function(){var a=this.g.D.i(),b=this.g.s.i(),d=this.o.n(),e=this.d;h.Q.Ac(a.src,function(c){function g(r,v,C,y,B,F,G,K,J){var w=Math.max;if(!u||!p||!y||!B||!K||!J)r.Ha("display","none");else{y=w(y,0);B=w(B,0);r.fa("path","m0,0l"+y*2+",0l"+y*2+","+B*2+"l0,"+B*2+"x");r.w("src", -n,"type","tile","position","0,0","origin",(F-0.5)/u+","+(G-0.5)/p,"size",h.Qa.gb(y*u/K)+"pt,"+h.Qa.gb(B*p/J)+"pt");r.ta(y,B);r.Ha("left",v+"px","top",C+"px","display","")}}var i=d.f,j=d.e,f=h.m("0"),k=a.O||(b?b.O:{t:f,r:f,b:f,l:f});f=k.t.a(e);var l=k.r.a(e),m=k.b.a(e);k=k.l.a(e);var o=a.slice,s=o.t.a(e),q=o.r.a(e),t=o.b.a(e);o=o.l.a(e);var n=a.src,u=c.f,p=c.e;g(this.N("tl"),0,0,k,f,0,0,o,s);g(this.N("t"),k,0,i-k-l,f,o,0,u-o-q,s);g(this.N("tr"),i-l,0,l,f,u-q,0,q,s);g(this.N("r"),i-l,f,l,j-f-m,u-q, -s,q,p-s-t);g(this.N("br"),i-l,j-m,l,m,u-q,p-t,q,t);g(this.N("b"),k,j-m,i-k-l,m,o,p-t,u-o-q,t);g(this.N("bl"),0,j-m,k,m,0,p-t,o,t);g(this.N("l"),0,f,k,j-f-m,0,s,o,p-s-t);g(this.N("c"),k,f,i-k-l,j-f-m,o,s,a.fill?u-o-q:0,p-s-t)},this)},N:function(a){return this.B("borderImage_"+a,this.H)},qc:function(){if(this.j()){var a=this.d,b=a.runtimeStyle,d=this.g.D.i().O;b.borderStyle="solid";if(d){b.borderTopWidth=d.t.a(a);b.borderRightWidth=d.r.a(a);b.borderBottomWidth=d.b.a(a);b.borderLeftWidth=d.l.a(a)}this.Bb()}}, -k:function(){var a=this.d.runtimeStyle;a.borderStyle="";if(this.Yb||!this.g.s.j())a.borderColor=a.borderWidth="";h.v.k.call(this)}});h.Gc=h.v.sa({H:1,ra:function(){var a=this.g;return a.na.L()||a.F.L()},j:function(){var a=this.g.na;return a.j()&&a.i().Ga[0]},Ca:function(){var a=this.d,b=this.g,d=b.na.i().Ga;b=b.F.i();var e=d.length,c=e,g=this.o.n(),i=g.f;g=g.e;for(var j,f,k,l,m,o,s,q,t,n;c--;){j=d[c];k=j.ke.a(a);l=j.le.a(a);m=j.$d.a(a);o=j.blur.a(a);j=j.color;s=j.Y();j=j.M(a);f=-m-o;if(!b&&o)b=h.lb.Bc; -q=this.Z(f,f,f,f,2,b);f=this.B("shadow"+c,this.H+(0.5-c/1E3));if(o){t=(m+o)*2+i;n=(m+o)*2+g;m=t?o*2/t:0;o=n?o*2/n:0;if(m>0.5||o>0.5){t=0.5/Math.max(m,o);m*=t;o*=t;s*=t*t}f.w("type","gradienttitle","color2",j,"focusposition",m+","+o,"focussize",1-m*2+","+(1-o*2),"opacity",0,"o:opacity2",s)}else f.w("type","solid","opacity",s);f.fa("path",q);f.w("color",j);f.Ha("left",k+"px","top",l+"px");f.ta(i,g)}for(;this.Ba("shadow"+e++););}});h.Lc=h.v.sa({H:6,ra:function(){var a=this.g;return this.d.src!==this.Sc|| -a.F.L()},j:function(){var a=this.g;return a.F.j()||a.K.ic()},Ca:function(){this.Sc=g;this.Ed();var a=this.B("img",this.H),b=this.o.n(),d=b.f;b=b.e;var e=this.g.s.i(),c=e&&e.O;e=this.d;var g=e.src,i=Math.round,j=this.g.da.i();if(!c||h.U<7){c=h.m("0");c={t:c,r:c,b:c,l:c}}a.fa("path",this.Z(i(c.t.a(e)+j.t.a(e)),i(c.r.a(e)+j.r.a(e)),i(c.b.a(e)+j.b.a(e)),i(c.l.a(e)+j.l.a(e)),2));a.w("type","frame","src",g,"position",(d?0.5/d:0)+","+(b?0.5/b:0));a.ta(d,b)},Ed:function(){this.d.runtimeStyle.filter="alpha(opacity=0)"}, -k:function(){h.v.k.call(this);this.d.runtimeStyle.filter=""}});h.mb=function(){function a(n,u){n.className+=" "+u}function b(n){var u=t.slice.call(arguments,1),p=u.length;setTimeout(function(){if(n)for(;p--;)a(n,u[p])},0)}function d(n){var u=t.slice.call(arguments,1),p=u.length;setTimeout(function(){if(n)for(;p--;){var r=u[p];r=q[r]||(q[r]=new RegExp("\\b"+r+"\\b","g"));n.className=n.className.replace(r,"")}},0)}function e(n){function u(){if(!T){var x,z,E=h.qa,N=n.currentStyle,I=N.getAttribute(g)=== -"true",Z=N.getAttribute(j)!=="false",$=N.getAttribute(f)!=="false";R=N.getAttribute(i);R=E>7?R!=="false":R==="true";if(!U){U=1;n.runtimeStyle.zoom=1;N=n;for(var aa=1;N=N.previousSibling;)if(N.nodeType===1){aa=0;break}aa&&a(n,o)}D.cb();if(I&&(z=D.n())&&(x=H.documentElement||H.body)&&(z.y>x.clientHeight||z.x>x.clientWidth||z.y+z.e<0||z.x+z.f<0)){if(!X){X=1;h.pb.ca(u)}}else{T=1;X=U=0;h.pb.Ka(u);if(E===9){A={K:new h.Hb(n),D:new h.Ib(n),s:new h.Jb(n),da:new h.Nb(n)};Q=[A.K,A.s,A.D,A.da];L=new h.oe(n,D, -A);M=[new h.me(n,D,A,L),new h.ne(n,D,A,L)]}else{A={K:new h.Hb(n),s:new h.Jb(n),D:new h.Ib(n),F:new h.lb(n),na:new h.Hc(n),da:new h.Nb(n),jb:new h.Oc(n)};Q=[A.K,A.s,A.D,A.F,A.na,A.da,A.jb];L=new h.Mc(n,D,A);M=[new h.Gc(n,D,A,L),new h.Dc(n,D,A,L),new h.Fc(n,D,A,L),new h.Ec(n,D,A,L)];n.tagName==="IMG"&&M.push(new h.Lc(n,D,A,L));L.ad=M}if(x=n.currentStyle.getAttribute(h.z+"watch-ancestors")){x=parseInt(x,10);z=0;for(I=n.parentNode;I&&(x==="NaN"||z++ 0 ) { - destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0; - distance = Math.abs(current) + destination; - duration = distance / speed; - } - - return { - destination: Math.round(destination), - duration: duration - }; - }; - - var _transform = _prefixStyle('transform'); - - me.extend(me, { - hasTransform: _transform !== false, - hasPerspective: _prefixStyle('perspective') in _elementStyle, - hasTouch: 'ontouchstart' in window, - hasPointer: navigator.msPointerEnabled, - hasTransition: _prefixStyle('transition') in _elementStyle - }); - - me.isAndroidBrowser = /Android/.test(window.navigator.appVersion) && /Version\/\d/.test(window.navigator.appVersion); - - me.extend(me.style = {}, { - transform: _transform, - transitionTimingFunction: _prefixStyle('transitionTimingFunction'), - transitionDuration: _prefixStyle('transitionDuration'), - transformOrigin: _prefixStyle('transformOrigin') - }); - - me.hasClass = function (e, c) { - var re = new RegExp("(^|\\s)" + c + "(\\s|$)"); - return re.test(e.className); - }; - - me.addClass = function (e, c) { - if ( me.hasClass(e, c) ) { - return; - } - - var newclass = e.className.split(' '); - newclass.push(c); - e.className = newclass.join(' '); - }; - - me.removeClass = function (e, c) { - if ( !me.hasClass(e, c) ) { - return; - } - - var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g'); - e.className = e.className.replace(re, ''); - }; - - me.offset = function (el) { - var left = -el.offsetLeft, - top = -el.offsetTop; - - // jshint -W084 - while (el = el.offsetParent) { - left -= el.offsetLeft; - top -= el.offsetTop; - } - // jshint +W084 - - return { - left: left, - top: top - }; - }; - - me.extend(me.eventType = {}, { - touchstart: 1, - touchmove: 1, - touchend: 1, - - mousedown: 2, - mousemove: 2, - mouseup: 2, - - MSPointerDown: 3, - MSPointerMove: 3, - MSPointerUp: 3 - }); - - me.extend(me.ease = {}, { - quadratic: { - style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', - fn: function (k) { - return k * ( 2 - k ); - } - }, - circular: { - style: 'cubic-bezier(0.1, 0.57, 0.1, 1)', // Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1) - fn: function (k) { - return Math.sqrt( 1 - ( --k * k ) ); - } - }, - back: { - style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)', - fn: function (k) { - var b = 4; - return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1; - } - }, - bounce: { - style: '', - fn: function (k) { - if ( ( k /= 1 ) < ( 1 / 2.75 ) ) { - return 7.5625 * k * k; - } else if ( k < ( 2 / 2.75 ) ) { - return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75; - } else if ( k < ( 2.5 / 2.75 ) ) { - return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375; - } else { - return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375; - } - } - }, - elastic: { - style: '', - fn: function (k) { - var f = 0.22, - e = 0.4; - - if ( k === 0 ) { return 0; } - if ( k == 1 ) { return 1; } - - return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 ); - } - } - }); - - me.tap = function (e, eventName) { - var ev = document.createEvent('Event'); - ev.initEvent(eventName, true, true); - ev.pageX = e.pageX; - ev.pageY = e.pageY; - e.target.dispatchEvent(ev); - }; - - me.click = function (e) { - var target = e.target, - ev; - - if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') { - ev = document.createEvent('MouseEvents'); - ev.initMouseEvent('click', true, true, e.view, 1, - target.screenX, target.screenY, target.clientX, target.clientY, - e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, - 0, null); - - ev._constructed = true; - target.dispatchEvent(ev); - } - }; - - return me; -})(); - -function IScroll (el, options) { - this.wrapper = typeof el == 'string' ? document.querySelector(el) : el; - this.scroller = this.wrapper.children[0]; - this.scrollerStyle = this.scroller.style; // cache style for better performance - - this.options = { - - resizeIndicator: true, - - mouseWheelSpeed: 20, - - snapThreshold: 0.334, - -// INSERT POINT: OPTIONS - - startX: 0, - startY: 0, - scrollY: true, - directionLockThreshold: 5, - momentum: true, - - bounce: true, - bounceTime: 600, - bounceEasing: '', - - preventDefault: true, - - HWCompositing: true, - useTransition: true, - useTransform: true - }; - - for ( var i in options ) { - this.options[i] = options[i]; - } - - // Normalize options - this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : ''; - - this.options.useTransition = utils.hasTransition && this.options.useTransition; - this.options.useTransform = utils.hasTransform && this.options.useTransform; - - this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough; - this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault; - - // If you want eventPassthrough I have to lock one of the axes - this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY; - this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX; - - // With eventPassthrough we also need lockDirection mechanism - this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough; - this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold; - - this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing; - - this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling; - - if ( this.options.tap === true ) { - this.options.tap = 'tap'; - } - - this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1; - -// INSERT POINT: NORMALIZATION - - // Some defaults - this.x = 0; - this.y = 0; - this.directionX = 0; - this.directionY = 0; - this._events = {}; - -// INSERT POINT: DEFAULTS - - this._init(); - this.refresh(); - - this.scrollTo(this.options.startX, this.options.startY); - this.enable(); -} - -IScroll.prototype = { - version: '5.0.4', - - _init: function () { - this._initEvents(); - - if ( this.options.scrollbars || this.options.indicators ) { - this._initIndicators(); - } - - if ( this.options.mouseWheel ) { - this._initWheel(); - } - - if ( this.options.snap ) { - this._initSnap(); - } - - if ( this.options.keyBindings ) { - this._initKeys(); - } - -// INSERT POINT: _init - - }, - - destroy: function () { - this._initEvents(true); - - this._execEvent('destroy'); - }, - - _transitionEnd: function (e) { - if ( e.target != this.scroller ) { - return; - } - - this._transitionTime(0); - if ( !this.resetPosition(this.options.bounceTime) ) { - this._execEvent('scrollEnd'); - } - }, - - _start: function (e) { - // React to left mouse button only - if ( utils.eventType[e.type] != 1 ) { - if ( e.button !== 0 ) { - return; - } - } - - if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) { - return; - } - - if ( this.options.preventDefault && !utils.isAndroidBrowser ) { - e.preventDefault(); // This seems to break default Android browser - } - - var point = e.touches ? e.touches[0] : e, - pos; - - this.initiated = utils.eventType[e.type]; - this.moved = false; - this.distX = 0; - this.distY = 0; - this.directionX = 0; - this.directionY = 0; - this.directionLocked = 0; - - this._transitionTime(); - - this.isAnimating = false; - this.startTime = utils.getTime(); - - if ( this.options.useTransition && this.isInTransition ) { - pos = this.getComputedPosition(); - - this._translate(Math.round(pos.x), Math.round(pos.y)); - this.isInTransition = false; - } - - this.startX = this.x; - this.startY = this.y; - this.absStartX = this.x; - this.absStartY = this.y; - this.pointX = point.pageX; - this.pointY = point.pageY; - - this._execEvent('scrollStart'); - }, - - _move: function (e) { - if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { - return; - } - - if ( this.options.preventDefault ) { // increases performance on Android? TODO: check! - e.preventDefault(); - } - - var point = e.touches ? e.touches[0] : e, - deltaX = this.hasHorizontalScroll ? point.pageX - this.pointX : 0, - deltaY = this.hasVerticalScroll ? point.pageY - this.pointY : 0, - timestamp = utils.getTime(), - newX, newY, - absDistX, absDistY; - - this.pointX = point.pageX; - this.pointY = point.pageY; - - this.distX += deltaX; - this.distY += deltaY; - absDistX = Math.abs(this.distX); - absDistY = Math.abs(this.distY); - - // We need to move at least 10 pixels for the scrolling to initiate - if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) { - return; - } - - // If you are scrolling in one direction lock the other - if ( !this.directionLocked && !this.options.freeScroll ) { - if ( absDistX > absDistY + this.options.directionLockThreshold ) { - this.directionLocked = 'h'; // lock horizontally - } else if ( absDistY >= absDistX + this.options.directionLockThreshold ) { - this.directionLocked = 'v'; // lock vertically - } else { - this.directionLocked = 'n'; // no lock - } - } - - if ( this.directionLocked == 'h' ) { - if ( this.options.eventPassthrough == 'vertical' ) { - e.preventDefault(); - } else if ( this.options.eventPassthrough == 'horizontal' ) { - this.initiated = false; - return; - } - - deltaY = 0; - } else if ( this.directionLocked == 'v' ) { - if ( this.options.eventPassthrough == 'horizontal' ) { - e.preventDefault(); - } else if ( this.options.eventPassthrough == 'vertical' ) { - this.initiated = false; - return; - } - - deltaX = 0; - } - - newX = this.x + deltaX; - newY = this.y + deltaY; - - // Slow down if outside of the boundaries - if ( newX > 0 || newX < this.maxScrollX ) { - newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX; - } - if ( newY > 0 || newY < this.maxScrollY ) { - newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY; - } - - this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0; - this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0; - - this.moved = true; - - this._translate(newX, newY); - -/* REPLACE START: _move */ - - if ( timestamp - this.startTime > 300 ) { - this.startTime = timestamp; - this.startX = this.x; - this.startY = this.y; - } - -/* REPLACE END: _move */ - - }, - - _end: function (e) { - if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) { - return; - } - - if ( this.options.preventDefault ) { - e.preventDefault(); // TODO: check if needed - } - - var point = e.changedTouches ? e.changedTouches[0] : e, - momentumX, - momentumY, - duration = utils.getTime() - this.startTime, - newX = Math.round(this.x), - newY = Math.round(this.y), - distanceX = Math.abs(newX - this.startX), - distanceY = Math.abs(newY - this.startY), - time = 0, - easing = ''; - - this.scrollTo(newX, newY); // ensures that the last position is rounded - - this.isInTransition = 0; - this.initiated = 0; - this.endTime = utils.getTime(); - - // reset if we are outside of the boundaries - if ( this.resetPosition(this.options.bounceTime) ) { - return; - } - - // we scrolled less than 10 pixels - if ( !this.moved ) { - if ( this.options.tap ) { - utils.tap(e, this.options.tap); - } - - if ( this.options.click ) { - utils.click(e); - } - - return; - } - - if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) { - this._execEvent('flick'); - return; - } - - // start momentum animation if needed - if ( this.options.momentum && duration < 300 ) { - momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0) : { destination: newX, duration: 0 }; - momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0) : { destination: newY, duration: 0 }; - newX = momentumX.destination; - newY = momentumY.destination; - time = Math.max(momentumX.duration, momentumY.duration); - this.isInTransition = 1; - } - - if ( this.options.snap ) { - var snap = this._nearestSnap(newX, newY); - this.currentPage = snap; - newX = snap.x; - newY = snap.y; - time = this.options.snapSpeed || Math.max( - Math.max( - Math.min(distanceX, 1000), - Math.min(distanceX, 1000) - ), 300); - - this.directionX = 0; - this.directionY = 0; - easing = this.options.bounceEasing; - } - - if ( newX != this.x || newY != this.y ) { - // change easing function when scroller goes out of the boundaries - if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) { - easing = utils.ease.quadratic; - } - - this.scrollTo(newX, newY, time, easing); - return; - } - - this._execEvent('scrollEnd'); - }, - - _resize: function () { - var that = this; - - clearTimeout(this.resizeTimeout); - - this.resizeTimeout = setTimeout(function () { - that.refresh(); - }, this.options.resizePolling); - }, - - resetPosition: function (time) { - var x = this.x, - y = this.y; - - time = time || 0; - - if ( !this.hasHorizontalScroll || this.x > 0 ) { - x = 0; - } else if ( this.x < this.maxScrollX ) { - x = this.maxScrollX; - } - - if ( !this.hasVerticalScroll || this.y > 0 ) { - y = 0; - } else if ( this.y < this.maxScrollY ) { - y = this.maxScrollY; - } - - if ( x == this.x && y == this.y ) { - return false; - } - - this.scrollTo(x, y, time, this.options.bounceEasing); - - return true; - }, - - disable: function () { - this.enabled = false; - }, - - enable: function () { - this.enabled = true; - }, - - refresh: function () { - var rf = this.wrapper.offsetHeight; // Force reflow - - this.wrapperWidth = this.wrapper.clientWidth; - this.wrapperHeight = this.wrapper.clientHeight; - -/* REPLACE START: refresh */ - - this.scrollerWidth = this.scroller.offsetWidth; - this.scrollerHeight = this.scroller.offsetHeight; - -/* REPLACE END: refresh */ - - this.maxScrollX = this.wrapperWidth - this.scrollerWidth; - this.maxScrollY = this.wrapperHeight - this.scrollerHeight; - - this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < 0; - this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < 0; - - if ( !this.hasHorizontalScroll ) { - this.maxScrollX = 0; - this.scrollerWidth = this.wrapperWidth; - } - - if ( !this.hasVerticalScroll ) { - this.maxScrollY = 0; - this.scrollerHeight = this.wrapperHeight; - } - - this.endTime = 0; - this.directionX = 0; - this.directionY = 0; - - this.wrapperOffset = utils.offset(this.wrapper); - - this._execEvent('refresh'); - - this.resetPosition(); - - if ( this.options.snap ) { - var snap = this._nearestSnap(this.x, this.y); - if ( this.x == snap.x && this.y == snap.y ) { - return; - } - - this.currentPage = snap; - this.scrollTo(snap.x, snap.y); - } - }, - - on: function (type, fn) { - if ( !this._events[type] ) { - this._events[type] = []; - } - - this._events[type].push(fn); - }, - - _execEvent: function (type) { - if ( !this._events[type] ) { - return; - } - - var i = 0, - l = this._events[type].length; - - if ( !l ) { - return; - } - - for ( ; i < l; i++ ) { - this._events[type][i].call(this); - } - }, - - scrollBy: function (x, y, time, easing) { - x = this.x + x; - y = this.y + y; - time = time || 0; - - this.scrollTo(x, y, time, easing); - }, - - scrollTo: function (x, y, time, easing) { - easing = easing || utils.ease.circular; - - if ( !time || (this.options.useTransition && easing.style) ) { - this._transitionTimingFunction(easing.style); - this._transitionTime(time); - this._translate(x, y); - } else { - this._animate(x, y, time, easing.fn); - } - }, - - scrollToElement: function (el, time, offsetX, offsetY, easing) { - el = el.nodeType ? el : this.scroller.querySelector(el); - - if ( !el ) { - return; - } - - var pos = utils.offset(el); - - pos.left -= this.wrapperOffset.left; - pos.top -= this.wrapperOffset.top; - - // if offsetX/Y are true we center the element to the screen - if ( offsetX === true ) { - offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2); - } - if ( offsetY === true ) { - offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2); - } - - pos.left -= offsetX || 0; - pos.top -= offsetY || 0; - - pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left; - pos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top; - - time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(pos.left)*2, Math.abs(pos.top)*2) : time; - - this.scrollTo(pos.left, pos.top, time, easing); - }, - - _transitionTime: function (time) { - time = time || 0; - this.scrollerStyle[utils.style.transitionDuration] = time + 'ms'; - - - if ( this.indicator1 ) { - this.indicator1.transitionTime(time); - } - - if ( this.indicator2 ) { - this.indicator2.transitionTime(time); - } - -// INSERT POINT: _transitionTime - - }, - - _transitionTimingFunction: function (easing) { - this.scrollerStyle[utils.style.transitionTimingFunction] = easing; - - - if ( this.indicator1 ) { - this.indicator1.transitionTimingFunction(easing); - } - - if ( this.indicator2 ) { - this.indicator2.transitionTimingFunction(easing); - } - - -// INSERT POINT: _transitionTimingFunction - - }, - - _translate: function (x, y) { - if ( this.options.useTransform ) { - -/* REPLACE START: _translate */ - - this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ; - -/* REPLACE END: _translate */ - - } else { - x = Math.round(x); - y = Math.round(y); - this.scrollerStyle.left = x + 'px'; - this.scrollerStyle.top = y + 'px'; - } - - this.x = x; - this.y = y; - - - if ( this.indicator1 ) { // usually the vertical - this.indicator1.updatePosition(); - } - - if ( this.indicator2 ) { - this.indicator2.updatePosition(); - } - -// INSERT POINT: _translate - - }, - - _initEvents: function (remove) { - var eventType = remove ? utils.removeEvent : utils.addEvent, - target = this.options.bindToWrapper ? this.wrapper : window; - - eventType(window, 'orientationchange', this); - eventType(window, 'resize', this); - - eventType(this.wrapper, 'mousedown', this); - eventType(target, 'mousemove', this); - eventType(target, 'mousecancel', this); - eventType(target, 'mouseup', this); - - if ( utils.hasPointer ) { - eventType(this.wrapper, 'MSPointerDown', this); - eventType(target, 'MSPointerMove', this); - eventType(target, 'MSPointerCancel', this); - eventType(target, 'MSPointerUp', this); - } - - if ( utils.hasTouch ) { - eventType(this.wrapper, 'touchstart', this); - eventType(target, 'touchmove', this); - eventType(target, 'touchcancel', this); - eventType(target, 'touchend', this); - } - - eventType(this.scroller, 'transitionend', this); - eventType(this.scroller, 'webkitTransitionEnd', this); - eventType(this.scroller, 'oTransitionEnd', this); - eventType(this.scroller, 'MSTransitionEnd', this); - }, - - getComputedPosition: function () { - var matrix = window.getComputedStyle(this.scroller, null), - x, y; - - if ( this.options.useTransform ) { - matrix = matrix[utils.style.transform].split(')')[0].split(', '); - x = +(matrix[12] || matrix[4]); - y = +(matrix[13] || matrix[5]); - } else { - x = +matrix.left.replace(/[^-\d]/g, ''); - y = +matrix.top.replace(/[^-\d]/g, ''); - } - - return { x: x, y: y }; - }, - - _initIndicators: function () { - var interactive = this.options.interactiveScrollbars, - defaultScrollbars = typeof this.options.scrollbars != 'object', - customStyle = typeof this.options.scrollbars != 'string', - indicator1, - indicator2; - - if ( this.options.scrollbars ) { - // Vertical scrollbar - if ( this.options.scrollY ) { - indicator1 = { - el: createDefaultScrollbar('v', interactive, this.options.scrollbars), - interactive: interactive, - defaultScrollbars: true, - customStyle: customStyle, - resize: this.options.resizeIndicator, - listenX: false - }; - - this.wrapper.appendChild(indicator1.el); - } - - // Horizontal scrollbar - if ( this.options.scrollX ) { - indicator2 = { - el: createDefaultScrollbar('h', interactive, this.options.scrollbars), - interactive: interactive, - defaultScrollbars: true, - customStyle: customStyle, - resize: this.options.resizeIndicator, - listenY: false - }; - - this.wrapper.appendChild(indicator2.el); - } - } else { - indicator1 = this.options.indicators.length ? this.options.indicators[0] : this.options.indicators; - indicator2 = this.options.indicators[1] && this.options.indicators[1]; - } - - if ( indicator1 ) { - this.indicator1 = new Indicator(this, indicator1); - } - - if ( indicator2 ) { - this.indicator2 = new Indicator(this, indicator2); - } - - this.on('refresh', function () { - if ( this.indicator1 ) { - this.indicator1.refresh(); - } - - if ( this.indicator2 ) { - this.indicator2.refresh(); - } - }); - - this.on('destroy', function () { - if ( this.indicator1 ) { - this.indicator1.destroy(); - this.indicator1 = null; - } - - if ( this.indicator2 ) { - this.indicator2.destroy(); - this.indicator2 = null; - } - }); - }, - - _initWheel: function () { - utils.addEvent(this.wrapper, 'mousewheel', this); - utils.addEvent(this.wrapper, 'DOMMouseScroll', this); - - this.on('destroy', function () { - utils.removeEvent(this.wrapper, 'mousewheel', this); - utils.removeEvent(this.wrapper, 'DOMMouseScroll', this); - }); - }, - - _wheel: function (e) { - if ( !this.enabled ) { - return; - } - - var wheelDeltaX, wheelDeltaY, - newX, newY, - that = this; - - // Execute the scrollEnd event after 400ms the wheel stopped scrolling - clearTimeout(this.wheelTimeout); - this.wheelTimeout = setTimeout(function () { - that._execEvent('scrollEnd'); - }, 400); - - e.preventDefault(); - - if ( 'wheelDeltaX' in e ) { - wheelDeltaX = e.wheelDeltaX / 120; - wheelDeltaY = e.wheelDeltaY / 120; - } else if ( 'wheelDelta' in e ) { - wheelDeltaX = wheelDeltaY = e.wheelDelta / 120; - } else if ( 'detail' in e ) { - wheelDeltaX = wheelDeltaY = -e.detail / 3; - } else { - return; - } - - wheelDeltaX *= this.options.mouseWheelSpeed; - wheelDeltaY *= this.options.mouseWheelSpeed; - - if ( !this.hasVerticalScroll ) { - wheelDeltaX = wheelDeltaY; - } - - newX = this.x + (this.hasHorizontalScroll ? wheelDeltaX * this.options.invertWheelDirection : 0); - newY = this.y + (this.hasVerticalScroll ? wheelDeltaY * this.options.invertWheelDirection : 0); - - if ( newX > 0 ) { - newX = 0; - } else if ( newX < this.maxScrollX ) { - newX = this.maxScrollX; - } - - if ( newY > 0 ) { - newY = 0; - } else if ( newY < this.maxScrollY ) { - newY = this.maxScrollY; - } - - this.scrollTo(newX, newY, 0); - -// INSERT POINT: _wheel - }, - - _initSnap: function () { - this.currentPage = {}; - - if ( typeof this.options.snap == 'string' ) { - this.options.snap = this.scroller.querySelectorAll(this.options.snap); - } - - this.on('refresh', function () { - var i = 0, l, - m = 0, n, - cx, cy, - x = 0, y, - stepX = this.options.snapStepX || this.wrapperWidth, - stepY = this.options.snapStepY || this.wrapperHeight, - el; - - this.pages = []; - - if ( this.options.snap === true ) { - cx = Math.round( stepX / 2 ); - cy = Math.round( stepY / 2 ); - - while ( x > -this.scrollerWidth ) { - this.pages[i] = []; - l = 0; - y = 0; - - while ( y > -this.scrollerHeight ) { - this.pages[i][l] = { - x: Math.max(x, this.maxScrollX), - y: Math.max(y, this.maxScrollY), - width: stepX, - height: stepY, - cx: x - cx, - cy: y - cy - }; - - y -= stepY; - l++; - } - - x -= stepX; - i++; - } - } else { - el = this.options.snap; - l = el.length; - n = -1; - - for ( ; i < l; i++ ) { - if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) { - m = 0; - n++; - } - - if ( !this.pages[m] ) { - this.pages[m] = []; - } - - x = Math.max(-el[i].offsetLeft, this.maxScrollX); - y = Math.max(-el[i].offsetTop, this.maxScrollY); - cx = x - Math.round(el[i].offsetWidth / 2); - cy = y - Math.round(el[i].offsetHeight / 2); - - this.pages[m][n] = { - x: x, - y: y, - width: el[i].offsetWidth, - height: el[i].offsetHeight, - cx: cx, - cy: cy - }; - - if ( x > this.maxScrollX ) { - m++; - } - } - } - - this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0); - - // Update snap threshold if needed - if ( this.options.snapThreshold % 1 === 0 ) { - this.snapThresholdX = this.options.snapThreshold; - this.snapThresholdY = this.options.snapThreshold; - } else { - this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold); - this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold); - } - }); - - this.on('flick', function () { - var time = this.options.snapSpeed || Math.max( - Math.max( - Math.min(Math.abs(this.x - this.startX), 1000), - Math.min(Math.abs(this.y - this.startY), 1000) - ), 300); - - this.goToPage( - this.currentPage.pageX + this.directionX, - this.currentPage.pageY + this.directionY, - time - ); - }); - }, - - _nearestSnap: function (x, y) { - var i = 0, - l = this.pages.length, - m = 0; - - // Check if we exceeded the snap threshold - if ( Math.abs(x - this.absStartX) < this.snapThresholdX && - Math.abs(y - this.absStartY) < this.snapThresholdY ) { - return this.currentPage; - } - - if ( x > 0 ) { - x = 0; - } else if ( x < this.maxScrollX ) { - x = this.maxScrollX; - } - - if ( y > 0 ) { - y = 0; - } else if ( y < this.maxScrollY ) { - y = this.maxScrollY; - } - - for ( ; i < l; i++ ) { - if ( x >= this.pages[i][0].cx ) { - x = this.pages[i][0].x; - break; - } - } - - l = this.pages[i].length; - - for ( ; m < l; m++ ) { - if ( y >= this.pages[0][m].cy ) { - y = this.pages[0][m].y; - break; - } - } - - if ( i == this.currentPage.pageX ) { - i += this.directionX; - - if ( i < 0 ) { - i = 0; - } else if ( i >= this.pages.length ) { - i = this.pages.length - 1; - } - - x = this.pages[i][0].x; - } - - if ( m == this.currentPage.pageY ) { - m += this.directionY; - - if ( m < 0 ) { - m = 0; - } else if ( m >= this.pages[0].length ) { - m = this.pages[0].length - 1; - } - - y = this.pages[0][m].y; - } - - return { - x: x, - y: y, - pageX: i, - pageY: m - }; - }, - - goToPage: function (x, y, time, easing) { - easing = easing || this.options.bounceEasing; - - if ( x >= this.pages.length ) { - x = this.pages.length - 1; - } else if ( x < 0 ) { - x = 0; - } - - if ( y >= this.pages[0].length ) { - y = this.pages[0].length - 1; - } else if ( y < 0 ) { - y = 0; - } - - var posX = this.pages[x][y].x, - posY = this.pages[x][y].y; - - time = time === undefined ? this.options.snapSpeed || Math.max( - Math.max( - Math.min(Math.abs(posX - this.x), 1000), - Math.min(Math.abs(posY - this.y), 1000) - ), 300) : time; - - this.currentPage = { - x: posX, - y: posY, - pageX: x, - pageY: y - }; - - this.scrollTo(posX, posY, time, easing); - }, - - next: function (time, easing) { - var x = this.currentPage.pageX, - y = this.currentPage.pageY; - - x++; - - if ( x >= this.pages.length && this.hasVerticalScroll ) { - x = 0; - y++; - } - - this.goToPage(x, y, time, easing); - }, - - prev: function (time, easing) { - var x = this.currentPage.pageX, - y = this.currentPage.pageY; - - x--; - - if ( x < 0 && this.hasVerticalScroll ) { - x = 0; - y--; - } - - this.goToPage(x, y, time, easing); - }, - - _initKeys: function (e) { - // default key bindings - var keys = { - pageUp: 33, - pageDown: 34, - end: 35, - home: 36, - left: 37, - up: 38, - right: 39, - down: 40 - }; - var i; - - // if you give me characters I give you keycode - if ( typeof this.options.keyBindings == 'object' ) { - for ( i in this.options.keyBindings ) { - if ( typeof this.options.keyBindings[i] == 'string' ) { - this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0); - } - } - } else { - this.options.keyBindings = {}; - } - - for ( i in keys ) { - this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i]; - } - - utils.addEvent(window, 'keydown', this); - - this.on('destroy', function () { - utils.removeEvent(window, 'keydown', this); - }); - }, - - _key: function (e) { - if ( !this.enabled ) { - return; - } - - var snap = this.options.snap, // we are using this alot, better to cache it - newX = snap ? this.currentPage.pageX : this.x, - newY = snap ? this.currentPage.pageY : this.y, - now = utils.getTime(), - prevTime = this.keyTime || 0, - acceleration = 0.250, - pos; - - if ( this.options.useTransition && this.isInTransition ) { - pos = this.getComputedPosition(); - - this._translate(Math.round(pos.x), Math.round(pos.y)); - this.isInTransition = false; - } - - this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0; - - switch ( e.keyCode ) { - case this.options.keyBindings.pageUp: - if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { - newX += snap ? 1 : this.wrapperWidth; - } else { - newY += snap ? 1 : this.wrapperHeight; - } - break; - case this.options.keyBindings.pageDown: - if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) { - newX -= snap ? 1 : this.wrapperWidth; - } else { - newY -= snap ? 1 : this.wrapperHeight; - } - break; - case this.options.keyBindings.end: - newX = snap ? this.pages.length-1 : this.maxScrollX; - newY = snap ? this.pages[0].length-1 : this.maxScrollY; - break; - case this.options.keyBindings.home: - newX = 0; - newY = 0; - break; - case this.options.keyBindings.left: - newX += snap ? -1 : 5 + this.keyAcceleration>>0; - break; - case this.options.keyBindings.up: - newY += snap ? 1 : 5 + this.keyAcceleration>>0; - break; - case this.options.keyBindings.right: - newX -= snap ? -1 : 5 + this.keyAcceleration>>0; - break; - case this.options.keyBindings.down: - newY -= snap ? 1 : 5 + this.keyAcceleration>>0; - break; - } - - if ( snap ) { - this.goToPage(newX, newY); - return; - } - - if ( newX > 0 ) { - newX = 0; - this.keyAcceleration = 0; - } else if ( newX < this.maxScrollX ) { - newX = this.maxScrollX; - this.keyAcceleration = 0; - } - - if ( newY > 0 ) { - newY = 0; - this.keyAcceleration = 0; - } else if ( newY < this.maxScrollY ) { - newY = this.maxScrollY; - this.keyAcceleration = 0; - } - - this.scrollTo(newX, newY, 0); - - this.keyTime = now; - }, - - _animate: function (destX, destY, duration, easingFn) { - var that = this, - startX = this.x, - startY = this.y, - startTime = utils.getTime(), - destTime = startTime + duration; - - function step () { - var now = utils.getTime(), - newX, newY, - easing; - - if ( now >= destTime ) { - that.isAnimating = false; - that._translate(destX, destY); - - if ( !that.resetPosition(that.options.bounceTime) ) { - that._execEvent('scrollEnd'); - } - - return; - } - - now = ( now - startTime ) / duration; - easing = easingFn(now); - newX = ( destX - startX ) * easing + startX; - newY = ( destY - startY ) * easing + startY; - that._translate(newX, newY); - - if ( that.isAnimating ) { - rAF(step); - } - } - - this.isAnimating = true; - step(); - }, - handleEvent: function (e) { - switch ( e.type ) { - case 'touchstart': - case 'MSPointerDown': - case 'mousedown': - this._start(e); - break; - case 'touchmove': - case 'MSPointerMove': - case 'mousemove': - this._move(e); - break; - case 'touchend': - case 'MSPointerUp': - case 'mouseup': - case 'touchcancel': - case 'MSPointerCancel': - case 'mousecancel': - this._end(e); - break; - case 'orientationchange': - case 'resize': - this._resize(); - break; - case 'transitionend': - case 'webkitTransitionEnd': - case 'oTransitionEnd': - case 'MSTransitionEnd': - this._transitionEnd(e); - break; - case 'DOMMouseScroll': - case 'mousewheel': - this._wheel(e); - break; - case 'keydown': - this._key(e); - break; - } - } -}; -function createDefaultScrollbar (direction, interactive, type) { - var scrollbar = document.createElement('div'), - indicator = document.createElement('div'); - - if ( type === true ) { - scrollbar.style.cssText = 'position:absolute;z-index:9999'; - indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px'; - } - - indicator.className = 'iScrollIndicator'; - - if ( direction == 'h' ) { - if ( type === true ) { - scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0'; - indicator.style.height = '100%'; - } - scrollbar.className = 'iScrollHorizontalScrollbar'; - } else { - if ( type === true ) { - scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px'; - indicator.style.width = '100%'; - } - scrollbar.className = 'iScrollVerticalScrollbar'; - } - - if ( !interactive ) { - scrollbar.style.pointerEvents = 'none'; - } - - scrollbar.appendChild(indicator); - - return scrollbar; -} - -function Indicator (scroller, options) { - this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el; - this.indicator = this.wrapper.children[0]; - this.indicatorStyle = this.indicator.style; - this.scroller = scroller; - - this.options = { - listenX: true, - listenY: true, - interactive: false, - resize: true, - defaultScrollbars: false, - speedRatioX: 0, - speedRatioY: 0 - }; - - for ( var i in options ) { - this.options[i] = options[i]; - } - - this.sizeRatioX = 1; - this.sizeRatioY = 1; - this.maxPosX = 0; - this.maxPosY = 0; - - if ( this.options.interactive ) { - utils.addEvent(this.indicator, 'touchstart', this); - utils.addEvent(this.indicator, 'MSPointerDown', this); - utils.addEvent(this.indicator, 'mousedown', this); - - utils.addEvent(window, 'touchend', this); - utils.addEvent(window, 'MSPointerUp', this); - utils.addEvent(window, 'mouseup', this); - } -} - -Indicator.prototype = { - handleEvent: function (e) { - switch ( e.type ) { - case 'touchstart': - case 'MSPointerDown': - case 'mousedown': - this._start(e); - break; - case 'touchmove': - case 'MSPointerMove': - case 'mousemove': - this._move(e); - break; - case 'touchend': - case 'MSPointerUp': - case 'mouseup': - case 'touchcancel': - case 'MSPointerCancel': - case 'mousecancel': - this._end(e); - break; - } - }, - - destroy: function () { - if ( this.options.interactive ) { - utils.removeEvent(this.indicator, 'touchstart', this); - utils.removeEvent(this.indicator, 'MSPointerDown', this); - utils.removeEvent(this.indicator, 'mousedown', this); - - utils.removeEvent(window, 'touchmove', this); - utils.removeEvent(window, 'MSPointerMove', this); - utils.removeEvent(window, 'mousemove', this); - - utils.removeEvent(window, 'touchend', this); - utils.removeEvent(window, 'MSPointerUp', this); - utils.removeEvent(window, 'mouseup', this); - } - - if ( this.options.defaultScrollbars ) { - this.wrapper.parentNode.removeChild(this.wrapper); - } - }, - - _start: function (e) { - var point = e.touches ? e.touches[0] : e; - - e.preventDefault(); - e.stopPropagation(); - - this.transitionTime(0); - - this.initiated = true; - this.moved = false; - this.lastPointX = point.pageX; - this.lastPointY = point.pageY; - - this.startTime = utils.getTime(); - - utils.addEvent(window, 'touchmove', this); - utils.addEvent(window, 'MSPointerMove', this); - utils.addEvent(window, 'mousemove', this); - - this.scroller._execEvent('scrollStart'); - }, - - _move: function (e) { - var point = e.touches ? e.touches[0] : e, - deltaX, deltaY, - newX, newY, - timestamp = utils.getTime(); - - this.moved = true; - - deltaX = point.pageX - this.lastPointX; - this.lastPointX = point.pageX; - - deltaY = point.pageY - this.lastPointY; - this.lastPointY = point.pageY; - - newX = this.x + deltaX; - newY = this.y + deltaY; - - this._pos(newX, newY); - - e.preventDefault(); - e.stopPropagation(); - }, - - _end: function (e) { - if ( !this.initiated ) { - return; - } - - this.initiated = false; - - e.preventDefault(); - e.stopPropagation(); - - utils.removeEvent(window, 'touchmove', this); - utils.removeEvent(window, 'MSPointerMove', this); - utils.removeEvent(window, 'mousemove', this); - - if ( this.moved ) { - this.scroller._execEvent('scrollEnd'); - } - }, - - transitionTime: function (time) { - time = time || 0; - this.indicatorStyle[utils.style.transitionDuration] = time + 'ms'; - }, - - transitionTimingFunction: function (easing) { - this.indicatorStyle[utils.style.transitionTimingFunction] = easing; - }, - - refresh: function () { - this.transitionTime(0); - - if ( this.options.listenX && !this.options.listenY ) { - this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none'; - } else if ( this.options.listenY && !this.options.listenX ) { - this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none'; - } else { - this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none'; - } - - if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) { - utils.addClass(this.wrapper, 'iScrollBothScrollbars'); - utils.removeClass(this.wrapper, 'iScrollLoneScrollbar'); - - if ( this.options.defaultScrollbars && this.options.customStyle ) { - if ( this.options.listenX ) { - this.wrapper.style.right = '8px'; - } else { - this.wrapper.style.bottom = '8px'; - } - } - } else { - utils.removeClass(this.wrapper, 'iScrollBothScrollbars'); - utils.addClass(this.wrapper, 'iScrollLoneScrollbar'); - - if ( this.options.defaultScrollbars && this.options.customStyle ) { - if ( this.options.listenX ) { - this.wrapper.style.right = '2px'; - } else { - this.wrapper.style.bottom = '2px'; - } - } - } - - var r = this.wrapper.offsetHeight; // force refresh - - if ( this.options.listenX ) { - this.wrapperWidth = this.wrapper.clientWidth; - if ( this.options.resize ) { - this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / this.scroller.scrollerWidth), 8); - this.indicatorStyle.width = this.indicatorWidth + 'px'; - } else { - this.indicatorWidth = this.indicator.clientWidth; - } - this.maxPosX = this.wrapperWidth - this.indicatorWidth; - this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX)); - } - - if ( this.options.listenY ) { - this.wrapperHeight = this.wrapper.clientHeight; - if ( this.options.resize ) { - this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / this.scroller.scrollerHeight), 8); - this.indicatorStyle.height = this.indicatorHeight + 'px'; - } else { - this.indicatorHeight = this.indicator.clientHeight; - } - - this.maxPosY = this.wrapperHeight - this.indicatorHeight; - this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY)); - } - - this.updatePosition(); - }, - - updatePosition: function () { - var x = Math.round(this.sizeRatioX * this.scroller.x) || 0, - y = Math.round(this.sizeRatioY * this.scroller.y) || 0; - - if ( !this.options.ignoreBoundaries ) { - if ( x < 0 ) { - x = 0; - } else if ( x > this.maxPosX ) { - x = this.maxPosX; - } - - if ( y < 0 ) { - y = 0; - } else if ( y > this.maxPosY ) { - y = this.maxPosY; - } - } - - this.x = x; - this.y = y; - - if ( this.scroller.options.useTransform ) { - this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ; - } else { - this.indicatorStyle.left = x + 'px'; - this.indicatorStyle.top = y + 'px'; - } - }, - - _pos: function (x, y) { - if ( x < 0 ) { - x = 0; - } else if ( x > this.maxPosX ) { - x = this.maxPosX; - } - - if ( y < 0 ) { - y = 0; - } else if ( y > this.maxPosY ) { - y = this.maxPosY; - } - - x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x; - y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y; - - this.scroller.scrollTo(x, y); - } -}; - -IScroll.ease = utils.ease; - -return IScroll; - -})(window, document, Math); \ No newline at end of file diff --git a/knowage/src/main/webapp/themes/geobi/scripts/utility.js b/knowage/src/main/webapp/themes/geobi/scripts/utility.js deleted file mode 100644 index 3b82d1e9858..00000000000 --- a/knowage/src/main/webapp/themes/geobi/scripts/utility.js +++ /dev/null @@ -1,258 +0,0 @@ -$(document).ready(function() { - - - // ---- Generic Stuff ---------------------------------------------------------------------------------------------------------- - - $('.box .fav-container').stop(true,true).hover(function(){ - $(this).find('.fav').animate({ - 'height': '62px' - },150,function(){ - $(this).find('.counter').stop().fadeIn(30); - }); - },function(){ - $(this).find('.fav .counter').stop().fadeOut(50,function(){ - $(this).parents('.fav').stop().animate({ - 'height': '40px' - },50); - }); - }); - - $('.list-container .box:nth-child(3n)').addClass('counter-3'); - $('.list-container .box:nth-child(4n)').addClass('counter-4'); - $('.list-container .box:nth-child(5n)').addClass('counter-5'); - - - // Sort order for datasets list and maps list - - // ATTENTION! DELETED lines from 27 to 48 - - toggleElements($('.list-actions .order')); // ATTENTION! ADDED - - $('.top-menu .reserved span').click(function(){ - reserved = $(this).parents('.reserved'); - loginPanel = reserved.find('.login-panel'); - /*if(reserved.hasClass('open')){ - - }else{ - loginPanel.slideDown(); - }*/ - loginPanel.slideToggle(); - reserved.toggleClass('open'); - }); - - - // ---- Map Panel ---------------------------------------------------------------------------------------------------------- - - - if($('body').hasClass('map-body')){ - - $('.panel-actions .btn-toggle').click(function(){ - if($(this).hasClass('open')){ - $('.panel').animate({ - 'right' : '-362px' - }); - $(this).removeClass('open'); - }else{ - $('.panel').animate({ - 'right' : '0' - }); - $(this).addClass('open'); - } - }); - - // Toggle map type - toggleElements($('.map-type')); - - - $(window).resize(function(){ - panelScroll(); - }); - - panelScroll(); - - if(!$('body').hasClass('lte-8')){ - $('#scroll .iScrollIndicator').mousedown(function() { - $(this).addClass('grabbing'); - }); - $('#scroll .iScrollIndicator').mouseup(function() { - $(this).removeClass('grabbing'); - }); - } - } - - - $('input, textarea, button, a, select').off('touchstart mousedown').on('touchstart mousedown', function(e) { - e.stopPropagation(); - }); - - accordion($('.group'),'.button','.slider'); - - $('.radio').each(function(){ - $(this).find('input').each(function(){ - $(this).change(function(){ - $(this).parents('.radio').find('.radio-option').removeClass('checked'); - if($(this).is(':checked')){ - $(this).parents('.radio-option').addClass('checked'); - } - }); - }); - }); - - $('.map-tools .map-tools-element').each(function(){ - $(this).find('.tools-content').data('maxWidth',$(this).find('.tools-content').outerWidth()).data('width',$(this).find('.tools-content').width()).data('height',$(this).find('.tools-content').height()).hide(); - $(this).data('originalWidth',$(this).width()); - }); - - $('.map-tools .icon').click(function(){ - tool = $(this).parents('.map-tools-element'); - height = tool.find('.tools-content').data('height'); - width = tool.find('.tools-content').data('width'); - /* - if($('body').hasClass('lte-7')){ - }else{*/ - tool.find('.tools-content').css({ - 'width': 0, - 'height': 0, - 'display': 'block' - }).animate({ - 'height': height + 'px', - 'width': width + 'px' - },200); - $(this).hide(); - if(tool.hasClass('layers')){ - contentWidth = tool.find('.tools-content').data('maxWidth'); - tool.animate({ - 'width': contentWidth + 'px' - },200); - } - /*}*/ - }); - - $('.map-tools .btn-close').click(function(){ - tool = $(this).parents('.map-tools-element'); - tool.find('.tools-content').fadeOut(200).animate({ - 'height': '0', - 'width': '0' - },300); - tool.find('.icon').show(); - if(tool.hasClass('layers')){ - contentWidth = tool.data('originalWidth'); - tool.animate({ - 'width': contentWidth + 'px' - },200); - } - }); - - function panelScroll(){ - panelHeight = $('.panel').height(); - buttonsHeight = $('.panel-buttons-container').outerHeight(); - maxHeight = panelHeight - buttonsHeight - 1; - $('.panel .scroll').css('max-height', maxHeight + 'px'); - if($('body').hasClass('lte-8')){ - $('#scroll').css('overflow-y','auto'); - }else{ - if($('#scroll').data('initialize') == '1'){ - panelScrollElement.refresh(); - }else{ - panelScrollElement = new IScroll('#scroll', { scrollbars: 'custom', mouseWheel: true, interactiveScrollbars: true}); - $('#scroll').data('initialize','1'); - } - if($('.panel .scroll').height() < maxHeight){ - $('.iScrollVerticalScrollbar').addClass('hidden'); - }else{ - $('.iScrollVerticalScrollbar').removeClass('hidden'); - } - } - } - - - function toggleElements(toggleContainer){ - curHeight = toggleContainer.css('height'); - toggleContainer.data('curHeight',curHeight).css('height','auto'); - maxHeight = toggleContainer.css('height'); - toggleContainer.data('maxHeight',maxHeight); - toggleContainer.css('height',toggleContainer.data('curHeight')); - toggleContainer.find('a').each(function(){ - $(this).click(function(){ - if(toggleContainer.hasClass('open')){ - toggleContainer.animate({ - 'height': toggleContainer.data('curHeight') - }); - toggleContainer.removeClass('open'); - }else{ - toggleContainer.animate({ - 'height': toggleContainer.data('maxHeight') - }); - toggleContainer.addClass('open'); - } - toggleContainer.find('li').removeClass('active last').find('.arrow').remove(); - $(this).parents('li').addClass('active').prependTo(toggleContainer).find('a').append(''); - toggleContainer.find('li:last').addClass('last'); - if($('body').hasClass('map-body')){ - setTimeout(function(){ - panelScroll(); - },400); - } - }); - }); - } - - function accordion(list,button,slider){ - list.each(function(){ - $(this).find(button).click(function(){ - $(this).parents('li').toggleClass('open').find(slider).slideToggle(); - if($('body').hasClass('map-body')){ - setTimeout(function(){ - panelScroll(); - },400); - } - }); - }); - } - - - - - // ---- PreFilled ---------------------------------------------------------------------------------------------------------- - - $.fn.preFilled = function() { - $(this).focus(function(){ - if( this.value == this.defaultValue ) { - this.value = ""; - } - }).blur(function(){ - if( !this.value.length ) { - this.value = this.defaultValue; - } - }); - }; - - $(".list-actions .search-form .field input,#l-password,#l-username").preFilled(); - - - // ---- CSS PIE - Round Corners ---------------------------------------------------------------------------------------------------------- - - if($('body').hasClass('lte-8')){ - $('.list-actions .btn-add').addClass('corner-type-a'); - $('.corner-type-a').each(function(){ - $(this).append(''); - }); - } - - if($('body').hasClass('lte-8')){ - if(window.PIE){ - $('.login-panel .submit input,.login-panel .field input,.panel-actions li.first,.panel-actions li.last,.panel-actions,.list-actions .search-form,.main-buttons a,.list-tab,.list-actions .order,.panel .btn-1,.panel .btn-2,.map-tools .btn-close').not('.panel .indicators .btn-2').each(function(){ - PIE.attach(this); - }); - } - } - - if($('body').hasClass('ie-8')){ - if(window.PIE){ - $('.box').each(function(){ - PIE.attach(this); - }); - } - } - -}); \ No newline at end of file diff --git a/knowage/src/main/webapp/themes/geobi/images/Logo_GeoBI_BETA.png b/knowage/src/main/webapp/themes/sbi_default/images/Logo_GeoBI_BETA.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/Logo_GeoBI_BETA.png rename to knowage/src/main/webapp/themes/sbi_default/images/Logo_GeoBI_BETA.png diff --git a/knowage/src/main/webapp/themes/geobi/images/arrow-1.png b/knowage/src/main/webapp/themes/sbi_default/images/arrow-1.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/arrow-1.png rename to knowage/src/main/webapp/themes/sbi_default/images/arrow-1.png diff --git a/knowage/src/main/webapp/themes/geobi/images/arrow-2.png b/knowage/src/main/webapp/themes/sbi_default/images/arrow-2.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/arrow-2.png rename to knowage/src/main/webapp/themes/sbi_default/images/arrow-2.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-arrow-order.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-arrow-order.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-arrow-order.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-arrow-order.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-btn-datasets.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-btn-datasets.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-btn-datasets.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-btn-datasets.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-btn-maps.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-btn-maps.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-btn-maps.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-btn-maps.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-btn-togglepanel.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-btn-togglepanel.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-btn-togglepanel.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-btn-togglepanel.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-cloud.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-cloud.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-cloud.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-cloud.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-fav-bottom.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-fav-bottom.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-fav-bottom.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-fav-bottom.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-fav-list-tab.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-fav-list-tab.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-fav-list-tab.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-fav-list-tab.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-fav-top.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-fav-top.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-fav-top.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-fav-top.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-feedback.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-feedback.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-feedback.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-feedback.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-hover.png b/knowage/src/main/webapp/themes/sbi_default/images/bg-hover.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-hover.png rename to knowage/src/main/webapp/themes/sbi_default/images/bg-hover.png diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-language-switcher.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-language-switcher.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-language-switcher.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-language-switcher.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-list-tab-active.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-list-tab-active.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-list-tab-active.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-list-tab-active.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-list-tab.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-list-tab.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-list-tab.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-list-tab.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-scrollbar-indicator.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-scrollbar-indicator.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-scrollbar-indicator.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-scrollbar-indicator.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-search.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-search.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-search.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-search.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/bg-top-bar.gif b/knowage/src/main/webapp/themes/sbi_default/images/bg-top-bar.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/bg-top-bar.gif rename to knowage/src/main/webapp/themes/sbi_default/images/bg-top-bar.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/btn-arrow.gif b/knowage/src/main/webapp/themes/sbi_default/images/btn-arrow.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/btn-arrow.gif rename to knowage/src/main/webapp/themes/sbi_default/images/btn-arrow.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/closedhand.cur b/knowage/src/main/webapp/themes/sbi_default/images/closedhand.cur similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/closedhand.cur rename to knowage/src/main/webapp/themes/sbi_default/images/closedhand.cur diff --git a/knowage/src/main/webapp/themes/geobi/images/corner-a.png b/knowage/src/main/webapp/themes/sbi_default/images/corner-a.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/corner-a.png rename to knowage/src/main/webapp/themes/sbi_default/images/corner-a.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-actions.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-actions.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-actions.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-actions.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-clone.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-clone.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-clone.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-clone.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-close.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-close.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-close.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-close.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-delete.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-delete.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-delete.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-delete.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-export.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-export.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-export.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-export.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-fav.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-fav.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-fav.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-fav.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-lock-small.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-lock-small.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-lock-small.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-lock-small.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-lock.gif b/knowage/src/main/webapp/themes/sbi_default/images/ico-lock.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-lock.gif rename to knowage/src/main/webapp/themes/sbi_default/images/ico-lock.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-map-tools.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-map-tools.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-map-tools.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-map-tools.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-map-type.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-map-type.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-map-type.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-map-type.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-newmap.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-newmap.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-newmap.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-newmap.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-qbe.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-qbe.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-qbe.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-qbe.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-register-form.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-register-form.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-register-form.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-register-form.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-scheduler.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-scheduler.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-scheduler.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-scheduler.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-tick.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-tick.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-tick.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-tick.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-view-cian.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-view-cian.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-view-cian.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-view-cian.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-view-green.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-view-green.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-view-green.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-view-green.png diff --git a/knowage/src/main/webapp/themes/geobi/images/ico-worksheet.png b/knowage/src/main/webapp/themes/sbi_default/images/ico-worksheet.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/ico-worksheet.png rename to knowage/src/main/webapp/themes/sbi_default/images/ico-worksheet.png diff --git a/knowage/src/main/webapp/themes/geobi/images/logo-pab.gif b/knowage/src/main/webapp/themes/sbi_default/images/logo-pab.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/logo-pab.gif rename to knowage/src/main/webapp/themes/sbi_default/images/logo-pab.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/logo-tis.gif b/knowage/src/main/webapp/themes/sbi_default/images/logo-tis.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/logo-tis.gif rename to knowage/src/main/webapp/themes/sbi_default/images/logo-tis.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/logo-ue.gif b/knowage/src/main/webapp/themes/sbi_default/images/logo-ue.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/logo-ue.gif rename to knowage/src/main/webapp/themes/sbi_default/images/logo-ue.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/logo.gif b/knowage/src/main/webapp/themes/sbi_default/images/logo.gif similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/logo.gif rename to knowage/src/main/webapp/themes/sbi_default/images/logo.gif diff --git a/knowage/src/main/webapp/themes/geobi/images/openhand.cur b/knowage/src/main/webapp/themes/sbi_default/images/openhand.cur similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/openhand.cur rename to knowage/src/main/webapp/themes/sbi_default/images/openhand.cur diff --git a/knowage/src/main/webapp/themes/geobi/images/placeholders/img-dataset-1.jpg b/knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-dataset-1.jpg similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/placeholders/img-dataset-1.jpg rename to knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-dataset-1.jpg diff --git a/knowage/src/main/webapp/themes/geobi/images/placeholders/img-legenda.jpg b/knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-legenda.jpg similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/placeholders/img-legenda.jpg rename to knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-legenda.jpg diff --git a/knowage/src/main/webapp/themes/geobi/images/placeholders/img-map.jpg b/knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-map.jpg similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/placeholders/img-map.jpg rename to knowage/src/main/webapp/themes/sbi_default/images/placeholders/img-map.jpg diff --git a/knowage/src/main/webapp/themes/geobi/images/placeholders/map.jpg b/knowage/src/main/webapp/themes/sbi_default/images/placeholders/map.jpg similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/placeholders/map.jpg rename to knowage/src/main/webapp/themes/sbi_default/images/placeholders/map.jpg diff --git a/knowage/src/main/webapp/themes/geobi/images/shadow.png b/knowage/src/main/webapp/themes/sbi_default/images/shadow.png similarity index 100% rename from knowage/src/main/webapp/themes/geobi/images/shadow.png rename to knowage/src/main/webapp/themes/sbi_default/images/shadow.png diff --git a/knowage/src/main/webapp/themes/sbi_default/jsp/login.jsp b/knowage/src/main/webapp/themes/sbi_default/jsp/login.jsp index 2170866a7c2..6efabdb4cd1 100644 --- a/knowage/src/main/webapp/themes/sbi_default/jsp/login.jsp +++ b/knowage/src/main/webapp/themes/sbi_default/jsp/login.jsp @@ -17,6 +17,7 @@ --%> +<%@page import="it.eng.spagobi.security.google.config.GoogleSignInConfig"%> <%@ page language="java" extends="it.eng.spago.dispatching.httpchannel.AbstractHttpJspPagePortlet" contentType="text/html; charset=UTF-8" @@ -55,10 +56,6 @@ .getConfigValue("SPAGOBI.SECURITY.ACTIVE_SIGNUP_FUNCTIONALITY"); boolean activeSignup = (strActiveSignup.equalsIgnoreCase("true"))?true:false; - String strInternalSecurity = serverConfig - .getConfigValue("SPAGOBI.SECURITY.PORTAL-SECURITY-CLASS.className"); - boolean isInternalSecurity = (strInternalSecurity - .indexOf("InternalSecurity") > 0) ? true : false; String roleToCheckLbl = (SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN") == null)?"" : SingletonConfig.getInstance().getConfigValue("SPAGOBI.SECURITY.ROLE_LOGIN"); @@ -142,6 +139,29 @@ "> + + <% if (GoogleSignInConfig.isEnabled()) {%> + <%-- Resources for Google Sign-In authentication --%> + + + + <% } %> @@ -150,9 +170,17 @@

+ + + <% if (GoogleSignInConfig.isEnabled()) { %> + <%-- Google button for authentication --%> +
+ + <% } else { %> + +
- - + <% } %> + + + <%-- Box that can be reused to display error messages, initially empty --%> + +
- + Image

@@ -100,7 +101,7 @@ along with this program. If not, see .

- + Image

@@ -108,7 +109,7 @@ along with this program. If not, see .

- + Image

@@ -117,7 +118,7 @@ along with this program. If not, see .

diff --git a/knowagebirtreportengine/src/main/webapp/META-INF/context.xml b/knowagebirtreportengine/src/main/webapp/META-INF/context.xml index 992097c80e2..e4a48a21ae8 100644 --- a/knowagebirtreportengine/src/main/webapp/META-INF/context.xml +++ b/knowagebirtreportengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - + diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTab.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTab.java index 3c3c7fe5674..05747edd130 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTab.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTab.java @@ -33,13 +33,31 @@ import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.TreeMap; +import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; + +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.AggregatorDelegate; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.AverageAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.CountAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.JsonPathAggregatorPlaceholder; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.MaxAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.MinAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.NotAvailablePlaceholder; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.NotDefinedAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.Placeholder; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.SumAggregator; +import it.eng.knowage.engine.cockpit.api.crosstable.placeholder.ValuePlaceholder; import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; import it.eng.spagobi.tools.dataset.common.datastore.IField; import it.eng.spagobi.tools.dataset.common.datastore.IRecord; @@ -83,6 +101,10 @@ public class CrossTab { public static final String PATH_SEPARATOR = "_S_"; // private static final String DATA_MATRIX_NA = "NA"; + /** + * + */ + @Deprecated private static final String DATA_MATRIX_NA = ""; private static final SimpleDateFormat DATE_FORMATTER = new SimpleDateFormat("dd/MM/yyyy"); private static final SimpleDateFormat TIMESTAMP_FORMATTER = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); @@ -94,10 +116,147 @@ public class CrossTab { private Node columnsRoot; private Node rowsRoot; - String[][] dataMatrix; + /** + * Relates something like "column_1" into datastore to "Field A" in the crosstab. + * @deprecated Alias can be duplicated + */ + @Deprecated + private Map dsColumnName2Alias = new HashMap(); + /** + * Relates something like "Field A" in the crosstab to "column_1" into datastore. + * @deprecated Alias can be duplicated + */ + @Deprecated + private Map alias2DsColumnName = new HashMap(); + /** + * Store the metadata related to the column name. + */ + private Map dsColumnName2Metadata = new HashMap(); + /** + * Store the metadata related to the column alias. + */ + private Map alias2Metadata = new HashMap(); + + private static final Placeholder NOT_AVAILABLE_PLACEHOLDER = new NotAvailablePlaceholder(); + + private String createJsonPathQueryFromNodes(Node currRow, Node currCol, MeasureInfo measure) { + Map colsValues = new TreeMap(); + String measureColName = alias2DsColumnName.get(measure.name); + + if (currRow.isMeasure()) { + measureColName = currRow.getColumnName(); + } else if (currCol.isMeasure()) { + measureColName = currCol.getColumnName(); + } + + // Get columns values from row + extractColumnsValuesFromNode(colsValues, currRow); + + // Get columns values from row + extractColumnsValuesFromNode(colsValues, currCol); + + // Create json path + StringBuilder ret = new StringBuilder("$"); + + if (!colsValues.isEmpty()) { + ret.append("[?("); + for (Iterator> iterator = colsValues.entrySet().iterator(); iterator.hasNext();) { + Entry entry = iterator.next(); + + String value = entry.getValue(); + value = StringEscapeUtils.escapeJavaScript(value); + + ret.append("@.") + .append(entry.getKey()) + .append(" == \"") + .append(value) + .append("\""); + + if (iterator.hasNext()) { + ret.append(" && "); + } + + } + + ret.append(")]").append("."); + } else { + ret.append(".*."); + } + + ret.append("[") + .append("'") + .append(measureColName) + .append("'"); + + // If there is a count... + if (!countMeasures.isEmpty()) { + // ... select the relative column + ret.append(",") + .append("'") + .append(countMeasures.get(0)) + .append("'"); + } + + ret.append("]"); + + String string = ret.toString(); + return string; + } + + private void extractColumnsValuesFromNode(Map colsValues, Node currNode) { + Node currRowParent = currNode; + while (currRowParent != null) { + String columnName = currRowParent.getColumnName(); + if (!currRowParent.isMeasure() && columnName != null) { + String value = currRowParent.getValue(); + colsValues.put(columnName, value); + } + currRowParent = currRowParent.getParentNode(); + } + } + + /** + * @param measure Measure used to determine the correct delegate + * @return An aggregator delegate instance + */ + private AggregatorDelegate getAggregatorDelegate(final MeasureInfo measure) { + AggregatorDelegate ret = null; + String aggregationFunction = measure.aggregationFunction; + + switch (aggregationFunction) { + case "SUM": + ret = SumAggregator.instance(); + break; + case "AVG": + ret = AverageAggregator.instance(); + break; + case "MAX": + ret = MaxAggregator.instance(); + break; + case "MIN": + ret = MinAggregator.instance(); + break; + case "COUNT": + ret = CountAggregator.instance(); + break; + case "COUNT_DISTINCT": + ret = NotDefinedAggregator.instance(); + break; + default: + ret = NotDefinedAggregator.instance(); + break; + } + + return ret; + } + + private DocumentContext parsedValuesDataStore = null; + + Placeholder[][] dataMatrix; private JSONObject config; private final List measures = new ArrayList(); private final List measuresToShowOnTotalsOrSubTotals = new ArrayList(); + private final List countMeasures = new ArrayList(); private CrosstabDefinition crosstabDefinition; private List rowHeadersTitles; private List rowsSum; // sum calculate for the rows (summ the row @@ -121,8 +280,8 @@ public class CrossTab { private List columnCordinates; private List measuresCordinates; - private List columnsSpecification = new ArrayList(); - private List rowsSpecification = new ArrayList(); + private List columnsSpecification = new ArrayList(); + private List rowsSpecification = new ArrayList(); private List columnsHeaderList = new ArrayList(); private List rowsHeaderList = new ArrayList(); @@ -207,9 +366,11 @@ private void init(CrosstabDefinition crosstabDefinition, JSONArray calculateFiel calculateCF(cf.getString("operation"), horizontal, cf.getInt("level"), cf.getString("name"), CellType.CF); } } + addSubtotals(); addTotals(); + List columns = crosstabDefinition.getColumns(); addHeaderTitles(columns, 0, columnsRoot); } @@ -287,14 +448,24 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD if (dataStoreMetadataFields.get(i) instanceof String) { continue; } - String name = dataStoreMetadataFields.getJSONObject(i).getString("name"); - String header = dataStoreMetadataFields.getJSONObject(i).getString("header"); + JSONObject jsonObject = dataStoreMetadataFields.getJSONObject(i); + String name = jsonObject.getString("name"); + String header = jsonObject.getString("header"); + + dsColumnName2Alias.put(name, header); + alias2DsColumnName.put(header, name); + dsColumnName2Metadata.put(name, jsonObject); + alias2Metadata.put(header, jsonObject); + if (columnsHeaderList.contains(header) || columnsHeaderIdList.contains(header)) { - columnsNameList.add(addNumberToColumnName(name, -1)); + columnsNameList.add(addNumberToColumnName(name)); } else if (rowsHeaderList.contains(header) || rowsHeaderIdList.contains(header)) { - rowsNameList.add(addNumberToColumnName(name, -1)); + rowsNameList.add(addNumberToColumnName(name)); } else if (measuresHeaderList.contains(header) || measuresHeaderIdList.contains(header)) { - measuresNameList.add(addNumberToColumnName(name, -1)); + measuresNameList.add(addNumberToColumnName(name)); + } + if ("___COUNT".equals(header)) { + countMeasures.add(name); } } @@ -325,8 +496,8 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD cellCount = actualRows * actualColumns * measuresCount; } - columnsRoot.updateFathers(); - rowsRoot.updateFathers(); +// columnsRoot.updateFathers(); +// rowsRoot.updateFathers(); if (index < dataStoredata.length()) { logger.debug("Crosstab cells number limit exceeded"); @@ -343,17 +514,23 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD for (index = 0; index < dataStoredata.length(); index++) { valueRecord = dataStoredata.getJSONObject(index); + List rowPathList = new ArrayList(); + List colPathList = new ArrayList(); + + columnPath = ""; for (int i = 0; i < columnsCount; i++) { String column = columnsNameList.get(i); Object value = valueRecord.get(column); String valueStr = null; - if (value == null) { + // String.valueOf() instead of toString() is used also to prevent NullPointerException + if (StringUtils.isEmpty(String.valueOf(value))) { valueStr = "null"; } else { valueStr = value.toString(); } columnPath = columnPath + PATH_SEPARATOR + valueStr; + colPathList.add(valueStr); } rowPath = ""; @@ -361,12 +538,14 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD String row = rowsNameList.get(i); Object value = valueRecord.get(row); String valueStr = null; - if (value == null) { + // String.valueOf() instead of toString() is used also to prevent NullPointerException + if (StringUtils.isEmpty(String.valueOf(value))) { valueStr = "null"; } else { valueStr = value.toString(); } - rowPath = rowPath + PATH_SEPARATOR + valueStr.toString(); + rowPath = rowPath + PATH_SEPARATOR + valueStr; + rowPathList.add(valueStr); } // defines array of data in according to coordinate: for (int i = 0; i < measuresNameList.size(); i++) { @@ -460,8 +639,6 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD addMeasuresToTree(rowsRoot, crosstabDefinition.getMeasures()); } config.put("columnsOverflow", columnsOverflow); - dataMatrix = getDataMatrix(columnsSpecification, rowsSpecification, columnCordinates, rowCordinates, measuresCordinates, data, measuresOnColumns, - measuresCount, columnsRoot.getLeafsNumber()); // put measures' info into measures variable for (int i = 0; i < crosstabDefinition.getMeasures().size(); i++) { @@ -478,6 +655,23 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD } } + /** + * !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! + * If you think that: + * + * dataStoredata.toString() + * + * Is useless think at the poor guy who lost 4 hours to understand + * that jsonpath works better with String than + * JSONObject/JSONArray. + * + * !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! + */ + parsedValuesDataStore = JsonPath.parse(dataStoredata.toString()); + + dataMatrix = getDataMatrix(columnsSpecification, rowsSpecification, columnCordinates, rowCordinates, measuresCordinates, data, measuresOnColumns, + measuresCount, columnsRoot.getLeafsNumber()); + celltypeOfColumns = new ArrayList(); celltypeOfRows = new ArrayList(); @@ -490,7 +684,7 @@ public CrossTab(JSONArray dataStoredata, JSONObject datastoreMetadata, CrosstabD } } - public String addNumberToColumnName(String columnName, int number) { + public String addNumberToColumnName(String columnName) { return columnName; } @@ -544,8 +738,8 @@ public CrossTab(IDataStore valuesDataStore, CrosstabDefinition crosstabDefinitio cellCount = actualRows * actualColumns * measuresCount; } - columnsRoot.updateFathers(); - rowsRoot.updateFathers(); +// columnsRoot.updateFathers(); +// rowsRoot.updateFathers(); columnsRoot.orderedSubtree(columnsSortKeysMap); rowsRoot.orderedSubtree(rowsSortKeysMap); @@ -604,8 +798,6 @@ public CrossTab(IDataStore valuesDataStore, CrosstabDefinition crosstabDefinitio addMeasuresToTree(rowsRoot, crosstabDefinition.getMeasures()); } config.put("columnsOverflow", columnsOverflow); - dataMatrix = getDataMatrix(columnsSpecification, rowsSpecification, columnCordinates, rowCordinates, null, data, measuresOnColumns, measuresCount, - columnsRoot.getLeafsNumber()); // put measures' info into measures variable IMetaData meta = valuesDataStore.getMetaData(); @@ -618,11 +810,33 @@ public CrossTab(IDataStore valuesDataStore, CrosstabDefinition crosstabDefinitio Measure relevantMeasure = crosstabDefinition.getMeasures().get(i - (meta.getFieldCount() - measuresCount)); MeasureInfo measureInfo = getMeasureInfo(fieldMeta, relevantMeasure); measures.add(measureInfo); + String aggregationFunction = measureInfo.getAggregationFunction(); + if ("COUNT".equals(aggregationFunction)) { + String column = alias2DsColumnName.get(measureInfo.getName()); + countMeasures.add(column); + } if (!measureInfo.excludeFromTotalAndSubtotal) { measuresToShowOnTotalsOrSubTotals.add(measureInfo); } } + /** + * !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! + * If you think that: + * + * dataStoredata.toString() + * + * Is useless think at the poor guy who lost 4 hours to understand + * that jsonpath works better with String than + * JSONObject/JSONArray. + * + * !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! WARNING !!! + */ + parsedValuesDataStore = JsonPath.parse(valuesDataStore.toString()); + + dataMatrix = getDataMatrix(columnsSpecification, rowsSpecification, columnCordinates, rowCordinates, null, data, measuresOnColumns, measuresCount, + columnsRoot.getLeafsNumber()); + celltypeOfColumns = new ArrayList(); celltypeOfRows = new ArrayList(); @@ -731,9 +945,9 @@ private JSONArray serializeCellType(List celltypes) { * : the number of the measures * @return the matrix that represent the data */ - private String[][] getDataMatrix(List columnsSpecification, List rowsSpecification, List columnCordinates, + private Placeholder/**/[][] getDataMatrix(List columnsSpecification, List rowsSpecification, List columnCordinates, List rowCordinates, List measuresCordinates, List data, boolean measuresOnColumns, int measuresLength, int columnsN) { - String[][] dataMatrix; + Placeholder/**/[][] dataMatrix; int x, y; int rowsN; @@ -743,20 +957,24 @@ private String[][] getDataMatrix(List columnsSpecification, List rowsN = (rowsSpecification.size() > 0 ? rowsSpecification.size() : 1) * measuresLength; } - dataMatrix = new String[rowsN][columnsN]; + dataMatrix = new Placeholder/**/[rowsN][columnsN]; // init the matrix for (int i = 0; i < rowsN; i++) { for (int j = 0; j < columnsN; j++) { - dataMatrix[i][j] = DATA_MATRIX_NA; + dataMatrix[i][j] = NOT_AVAILABLE_PLACEHOLDER; } } if (measuresOnColumns) { for (int i = 0; i < data.size(); i = i + measuresLength) { for (int j = 0; j < measuresLength; j++) { + String rowCoordinate = null; + String columnCoordinate = null; + if (rowsSpecification.size() > 0) { - x = rowsSpecification.indexOf(rowCordinates.get(i + j)); + rowCoordinate = rowCordinates.get(i + j); + x = rowsSpecification.indexOf(rowCoordinate); if (x < 0) { continue; // elements not found because crosstab is // too big and it was truncated @@ -765,7 +983,8 @@ private String[][] getDataMatrix(List columnsSpecification, List x = 0; // crosstab with no attributes on rows } if (columnsSpecification.size() > 0) { - y = columnsSpecification.indexOf(columnCordinates.get(i + j)); + columnCoordinate = columnCordinates.get(i + j); + y = columnsSpecification.indexOf(columnCoordinate); if (y < 0) { continue; // elements not found because crosstab is // too big and it was truncated @@ -774,15 +993,21 @@ private String[][] getDataMatrix(List columnsSpecification, List y = 0; // crosstab with no attributes on columns } if ((y * measuresLength + j) < columnsN && (y * measuresLength + j) >= 0) { - dataMatrix[x][y * measuresLength + j] = data.get(i + j); + MeasureInfo measureInfo = measures.get(j); + ValuePlaceholder valuePlaceholder = new ValuePlaceholder(data.get(i + j), measureInfo); + dataMatrix[x][y * measuresLength + j] = valuePlaceholder; } } } } else { for (int i = 0; i < data.size(); i = i + measuresLength) { for (int j = 0; j < measuresLength; j++) { + String rowCoordinate = null; + String columnCoordinate = null; + if (rowsSpecification.size() > 0) { - x = rowsSpecification.indexOf(rowCordinates.get(i + j)); + rowCoordinate = rowCordinates.get(i + j); + x = rowsSpecification.indexOf(rowCoordinate); if (x < 0) { continue; // elements not found because crosstab is // too big and it was truncated @@ -792,7 +1017,8 @@ private String[][] getDataMatrix(List columnsSpecification, List } if (columnsSpecification.size() > 0) { - y = columnsSpecification.indexOf(columnCordinates.get(i + j)); + columnCoordinate = columnCordinates.get(i + j); + y = columnsSpecification.indexOf(columnCoordinate); if (y < 0) { continue; // elements not found because crosstab is // too big and it was truncated @@ -802,7 +1028,9 @@ private String[][] getDataMatrix(List columnsSpecification, List } if (y < columnsN && y >= 0) { - dataMatrix[x * measuresLength + j][y] = data.get(i + j); + MeasureInfo measureInfo = measures.get(j); + ValuePlaceholder valuePlaceholder = new ValuePlaceholder(data.get(i + j), measureInfo); + dataMatrix[x * measuresLength + j][y] = valuePlaceholder; } } } @@ -834,47 +1062,6 @@ public JSONArray getJSONDataMatrix() { return matrix; } - /** - * Add to the root (columnRoot or rowRoot) a path from the root to a leaf. A record contains both the columns definition and the rows definition: (it may be - * something like that: C1 C2 C3 R1 R2 M1 M1, where Ci represent a column, Ri represent a row, Mi a measure). So for take a column path (C1 C2 C3), we need - * need a start and end position in the record (in this case 0,3) - * - * @param root - * : the node in witch add the record - * @param record - * @param startPosition - * @param endPosition - */ - private boolean addRecord(Node root, JSONObject datasetRecords, List attributeFieldsName) { - boolean toReturn = false; - String valueField; - String descriptionField; - Node node; - Node nodeToCheck = root; - int nodePosition; - - for (int indexFields = 0; indexFields < attributeFieldsName.size(); indexFields++) { - try { - valueField = datasetRecords.getString(attributeFieldsName.get(indexFields)); - descriptionField = valueField; //temporaneo: recuperare dinamicamente il valore - } catch (JSONException e) { - logger.error("Error getting the values from the dataset"); - throw new SpagoBIEngineRuntimeException("Error getting the values from the dataset"); - } - node = new Node(valueField, descriptionField); //aggiungere il valore della colonna di ordinamento e chiamare il costruttore Node(value, description) dove value è il valore della colonna di ordinamento - - nodePosition = nodeToCheck.getChilds().indexOf(node); - if (nodePosition < 0) { - toReturn = true; - nodeToCheck.addChild(node); - nodeToCheck = node; - } else { - nodeToCheck = nodeToCheck.getChilds().get(nodePosition); - } - } - return toReturn; - } - /** * Add to the root (columnRoot or rowRoot) a path from the root to a leaf. A record contains both the columns definition and the rows definition: (it may be * something like that: C1 C2 C3 R1 R2 M1 M1, where Ci represent a column, Ri represent a row, Mi a measure). So for take a column path (C1 C2 C3), we need @@ -888,23 +1075,26 @@ private boolean addRecord(Node root, JSONObject datasetRecords, List att */ private boolean addRecord(Node root, JSONObject datasetRecords, List attributeFieldsName, List orderingList ) { boolean toReturn = false; - String valueField; - String descriptionField; + String columnName = null; + String valueField = null; + String descriptionField = null; Node node; Node nodeToCheck = root; int nodePosition; for (int indexFields = 0; indexFields < attributeFieldsName.size(); indexFields++) { try { - String valueColumn = getValueFromOrderingId (orderingList, attributeFieldsName.get(indexFields)); - if (valueColumn == null || valueColumn.equals("")) valueColumn = attributeFieldsName.get(indexFields); //value = description + columnName = attributeFieldsName.get(indexFields); + String valueColumn = getValueFromOrderingId (orderingList, columnName); + if (valueColumn == null || valueColumn.equals("")) valueColumn = columnName; //value = description valueField = datasetRecords.getString(valueColumn); - descriptionField = datasetRecords.getString(attributeFieldsName.get(indexFields)); + descriptionField = datasetRecords.getString(columnName); } catch (JSONException e) { logger.error("Error getting the values from the dataset"); throw new SpagoBIEngineRuntimeException("Error getting the values from the dataset"); } - node = new Node(valueField, descriptionField); + JSONObject jsonObject = dsColumnName2Metadata.get(columnName); + node = new Node(columnName, valueField, descriptionField, jsonObject); nodePosition = nodeToCheck.getChilds().indexOf(node); if (nodePosition < 0) { @@ -992,23 +1182,23 @@ private List getLeafsPathList(Node n) { private List visit(Node n, String prefix) { List toReturn = new ArrayList(); - if (n.getChilds().size() == 0) { + String description = n.getDescription(); + if (StringUtils.isEmpty(description)) { + description = "null"; + } + if (n.getChilds().isEmpty()) { if (prefix.equals(PATH_SEPARATOR)) { -// toReturn.add(prefix + (n.getValue())); - toReturn.add(prefix + (n.getDescription())); + toReturn.add(prefix + description); } else { -// toReturn.add(prefix + PATH_SEPARATOR + (n.getValue())); - toReturn.add(prefix + PATH_SEPARATOR + (n.getDescription())); + toReturn.add(prefix + PATH_SEPARATOR + description); } return toReturn; } else { for (int i = 0; i < n.getChilds().size(); i++) { if (prefix.equals(PATH_SEPARATOR)) { -// toReturn.addAll(visit(n.getChilds().get(i), prefix + (n.getValue()))); - toReturn.addAll(visit(n.getChilds().get(i), prefix + (n.getDescription()))); + toReturn.addAll(visit(n.getChilds().get(i), prefix + description)); } else { -// toReturn.addAll(visit(n.getChilds().get(i), prefix + PATH_SEPARATOR + (n.getValue()))); - toReturn.addAll(visit(n.getChilds().get(i), prefix + PATH_SEPARATOR + (n.getDescription()))); + toReturn.addAll(visit(n.getChilds().get(i), prefix + PATH_SEPARATOR + description)); } } return toReturn; @@ -1023,8 +1213,10 @@ private List visit(Node n, String prefix) { */ private void addMeasuresToTree(Node root, List measures) { List measuresNodes = new ArrayList(); - for (int i = 0; i < measures.size(); i++) { - measuresNodes.add(new Node(measures.get(i).getAlias())); + for (Measure measure : measures) { + String alias = measure.getAlias(); + String columnName = alias2DsColumnName.get(alias); + measuresNodes.add(new Node(columnName, alias, alias, true)); } addMeasuresToLeafs(root, measuresNodes); @@ -1037,6 +1229,7 @@ private void addMeasuresToLeafs(Node node, List measuresNodes) { Node n = measuresNodes.get(i).clone(); node.addChild(n); } +// node.updateFathers(); } else { for (int i = 0; i < node.getChilds().size(); i++) { addMeasuresToLeafs(node.getChilds().get(i), measuresNodes); @@ -1138,13 +1331,13 @@ public String getMeasureScaleFactor(String name) { public static class MeasureInfo { - String name; - String type; - String format; - String id; + final String name; + final String type; + final String format; + final String id; String scaleFactor; - String aggregationFunction; - Boolean excludeFromTotalAndSubtotal; + final String aggregationFunction; + final Boolean excludeFromTotalAndSubtotal; public MeasureInfo(String name, String id, String type, String format, String aggregationFunction, Boolean excludeFromTotalAndSubtotal) { this.name = name; @@ -1187,6 +1380,11 @@ public Boolean getExcludeFromTotalAndSubtotal() { return excludeFromTotalAndSubtotal; } + @Override + public String toString() { + return "MeasureInfo [id=" + id + ", type=" + type + ", aggregationFunction=" + aggregationFunction + "]"; + } + } /************************************************* @@ -1389,7 +1587,7 @@ private void calculateCFSub(String operation, Node node, boolean horizontal, int } node.addChild(mergedNode); - addCrosstabDataLine(positionToAdd, calculatedFieldResult, horizontal, celltype); + addCrosstabDataLine(node, positionToAdd, calculatedFieldResult, horizontal, celltype); } } @@ -1592,6 +1790,8 @@ private String executeOperationOnNumbers(List data, List op) { * Sum the values of the rows (the right pannel) * * @param measuresOnRow + * + * TODO */ private List getTotalsOnRows(boolean measuresOnRow) { List result = new ArrayList(); @@ -1600,48 +1800,48 @@ private List getTotalsOnRows(boolean measuresOnRow) { if (!measuresOnRow) { measures = this.measuresToShowOnTotalsOrSubTotals.size(); } - int iteration = dataMatrix[0].length / measures; +// int iteration = dataMatrix[0].length / measures; for (int measureId = 0; measureId < measures; measureId++) { - MeasureInfo measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureId); - String aggregationFunction = measureInfo.getAggregationFunction(); +// MeasureInfo measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureId); +// String aggregationFunction = measureInfo.getAggregationFunction(); st = new double[dataMatrix.length]; - for (int i = 0; i < dataMatrix.length; i++) { - if (measuresOnRow) { - int measureIndex = i % this.measuresToShowOnTotalsOrSubTotals.size(); - measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureIndex); - aggregationFunction = measureInfo.getAggregationFunction(); - } - List values = new ArrayList(); - if (!measureInfo.excludeFromTotalAndSubtotal) { - for (int j = 0; j < iteration; j++) { - try { - if (getCellType(i, j * measures + measureId).equals(CellType.DATA) || getCellType(i, j * measures + measureId).equals(CellType.TOTAL)) { - String value = dataMatrix[i][j * measures + measureId]; - if (!value.equals(DATA_MATRIX_NA)) { - values.add(new Double(value)); - } - } - } catch (Exception e) { - logger.debug("Cant format the number " + (dataMatrix[i][j * measures + measureId])); - } - } - } - if (!values.isEmpty()) { - if (aggregationFunction.equalsIgnoreCase("MAX")) { - st[i] = getMax(values); - } else if (aggregationFunction.equalsIgnoreCase("MIN")) { - st[i] = getMin(values); - } else if (aggregationFunction.equalsIgnoreCase("SUM")) { - st[i] = getSum(values); - } else if (aggregationFunction.equalsIgnoreCase("COUNT")) { - st[i] = getCount(values); - } else if (aggregationFunction.equalsIgnoreCase("AVG")) { - st[i] = getAvg(values); - } else if (aggregationFunction.equalsIgnoreCase("COUNT_DISTINCT")) { - st[i] = getCountDistinct(values); - } - } - } +// for (int i = 0; i < dataMatrix.length; i++) { +// if (measuresOnRow) { +// int measureIndex = i % this.measuresToShowOnTotalsOrSubTotals.size(); +// measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureIndex); +// aggregationFunction = measureInfo.getAggregationFunction(); +// } +// List values = new ArrayList(); +// if (!measureInfo.excludeFromTotalAndSubtotal) { +// for (int j = 0; j < iteration; j++) { +// try { +// if (getCellType(i, j * measures + measureId).equals(CellType.DATA) || getCellType(i, j * measures + measureId).equals(CellType.TOTAL)) { +// String value = dataMatrix[i][j * measures + measureId]; +// if (!value.equals(DATA_MATRIX_NA)) { +// values.add(new Double(value)); +// } +// } +// } catch (Exception e) { +// logger.debug("Cant format the number " + (dataMatrix[i][j * measures + measureId])); +// } +// } +// } +// if (!values.isEmpty()) { +// if (aggregationFunction.equalsIgnoreCase("MAX")) { +// st[i] = getMax(values); +// } else if (aggregationFunction.equalsIgnoreCase("MIN")) { +// st[i] = getMin(values); +// } else if (aggregationFunction.equalsIgnoreCase("SUM")) { +// st[i] = getSum(values); +// } else if (aggregationFunction.equalsIgnoreCase("COUNT")) { +// st[i] = getCount(values); +// } else if (aggregationFunction.equalsIgnoreCase("AVG")) { +// st[i] = getAvg(values); +// } else if (aggregationFunction.equalsIgnoreCase("COUNT_DISTINCT")) { +// st[i] = getCountDistinct(values); +// } +// } +// } result.add(toStringArray(st)); } return result; @@ -1678,31 +1878,32 @@ private double getCountDistinct(List values) { return distinctValues.size(); } - - + /** + * TODO + */ private String[] getTotalsOfRows(int start, int length) { double[] st = new double[dataMatrix[0].length]; - for (int i = 0; i < dataMatrix[0].length; i++) { - MeasureInfo measureInfo = measures.get(i % measures.size()); - boolean excludeFromTotalAndSubtotal = measureInfo.excludeFromTotalAndSubtotal; - if (excludeFromTotalAndSubtotal) { - st[i] = Double.NaN; - } else { - for (int j = start; j < length + start; j++) { - try { - if (!excludeFromTotalAndSubtotal && getCellType(j, i).equals(CellType.DATA)) { - String value = dataMatrix[j][i]; - if (!value.equals(DATA_MATRIX_NA)) { - st[i] = st[i] + new Double(value); - } - } - } catch (Exception e) { - logger.debug("Cant format the number " + (dataMatrix[j][i])); - } - } - } - } +// for (int i = 0; i < dataMatrix[0].length; i++) { +// MeasureInfo measureInfo = measures.get(i % measures.size()); +// boolean excludeFromTotalAndSubtotal = measureInfo.excludeFromTotalAndSubtotal; +// if (excludeFromTotalAndSubtotal) { +// st[i] = Double.NaN; +// } else { +// for (int j = start; j < length + start; j++) { +// try { +// if (!excludeFromTotalAndSubtotal && getCellType(j, i).equals(CellType.DATA)) { +// String value = dataMatrix[j][i]; +// if (!value.equals(DATA_MATRIX_NA)) { +// st[i] = st[i] + new Double(value); +// } +// } +// } catch (Exception e) { +// logger.debug("Cant format the number " + (dataMatrix[j][i])); +// } +// } +// } +// } return toStringArray(st); } @@ -1721,131 +1922,142 @@ private String[] toStringArray(double[] doubleArray) { * * @param measuresOnRow * @return + * + * TODO */ private List getTotalsOnColumns(boolean measuresOnRow) { List result = new ArrayList(); double[] st; - int measures = 1; //default for measures on column : it sums 1 column at a time - if (measuresOnRow) { - measures = this.measures.size(); - } - int iteration = dataMatrix.length / measures; - for (int measureId = 0; measureId < measures; measureId++) { - MeasureInfo measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureId); +// int measures = 1; //default for measures on column : it sums 1 column at a time +// if (measuresOnRow) { +// measures = this.measures.size(); +// } +// int iteration = dataMatrix.length / measures; +// for (int measureId = 0; measureId < measures; measureId++) { +// MeasureInfo measureInfo = this.measuresToShowOnTotalsOrSubTotals.get(measureId); st = new double[dataMatrix[0].length]; - Map> valuesMap = new HashMap>(); - for (int i = 0; i < iteration; i++) { - for (int j = 0; j < dataMatrix[0].length; j++) { - MeasureInfo measureInfoNew = this.measures.get(j % this.measures.size()); - try { - if (getCellType(i * measures + measureId, j).equals(CellType.DATA) || getCellType(i * measures + measureId, j).equals(CellType.SUBTOTAL) || getCellType(i * measures + measureId, j).equals(CellType.TOTAL)) { - String value = dataMatrix[i * measures + measureId][j]; - if (measureInfoNew.excludeFromTotalAndSubtotal) { - if (!valuesMap.containsKey(j)) { - valuesMap.put(j, Collections.EMPTY_LIST); - } - } else if (!value.equals(DATA_MATRIX_NA)) { - if (valuesMap.containsKey(j)) { - valuesMap.get(j).add( new Double(value)); - } else { - List list = new ArrayList(); - list.add(new Double(value)); - valuesMap.put(j,list ); - } - } - } - } catch (Exception e) { - logger.debug("Cant format the number " + (dataMatrix[i * measures + measureId][j])); - } - } - } - - Iterator>> it = valuesMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry> pair = it.next(); - List values = pair.getValue(); - Integer index = pair.getKey(); - int measureIndex; - if (measuresOnRow) { - measureIndex = measureId; - } else { - measureIndex = index % this.measuresToShowOnTotalsOrSubTotals.size(); - } - - String aggregationFunction = measureInfo.getAggregationFunction(); - if (!values.isEmpty()) { - if (aggregationFunction.equalsIgnoreCase("MAX")) { - st[index] = getMax(values); - } else if (aggregationFunction.equalsIgnoreCase("MIN")) { - st[index] = getMin(values); - } else if (aggregationFunction.equalsIgnoreCase("SUM")) { - st[index] = getSum(values); - } else if (aggregationFunction.equalsIgnoreCase("COUNT")) { - st[index] = getCount(values); - } else if (aggregationFunction.equalsIgnoreCase("AVG")) { - st[index] = getAvg(values); - } else if (aggregationFunction.equalsIgnoreCase("COUNT_DISTINCT")) { - st[index] = getCountDistinct(values); - } - } else { - st[index] = Double.NaN; - } - - } - +// Map> valuesMap = new HashMap>(); +// for (int i = 0; i < iteration; i++) { +// for (int j = 0; j < dataMatrix[0].length; j++) { +// MeasureInfo measureInfoNew = this.measures.get(j % this.measures.size()); +// try { +// if (getCellType(i * measures + measureId, j).equals(CellType.DATA) || getCellType(i * measures + measureId, j).equals(CellType.SUBTOTAL) || getCellType(i * measures + measureId, j).equals(CellType.TOTAL)) { +// String value = dataMatrix[i * measures + measureId][j]; +// if (measureInfoNew.excludeFromTotalAndSubtotal) { +// if (!valuesMap.containsKey(j)) { +// valuesMap.put(j, Collections.EMPTY_LIST); +// } +// } else if (!value.equals(DATA_MATRIX_NA)) { +// if (valuesMap.containsKey(j)) { +// valuesMap.get(j).add( new Double(value)); +// } else { +// List list = new ArrayList(); +// list.add(new Double(value)); +// valuesMap.put(j,list ); +// } +// } +// } +// } catch (Exception e) { +// logger.debug("Cant format the number " + (dataMatrix[i * measures + measureId][j])); +// } +// } +// } +// +// Iterator>> it = valuesMap.entrySet().iterator(); +// while (it.hasNext()) { +// Map.Entry> pair = it.next(); +// List values = pair.getValue(); +// Integer index = pair.getKey(); +// int measureIndex; +// if (measuresOnRow) { +// measureIndex = measureId; +// } else { +// measureIndex = index % this.measuresToShowOnTotalsOrSubTotals.size(); +// } +// +// String aggregationFunction = measureInfo.getAggregationFunction(); +// if (!values.isEmpty()) { +// if (aggregationFunction.equalsIgnoreCase("MAX")) { +// st[index] = getMax(values); +// } else if (aggregationFunction.equalsIgnoreCase("MIN")) { +// st[index] = getMin(values); +// } else if (aggregationFunction.equalsIgnoreCase("SUM")) { +// st[index] = getSum(values); +// } else if (aggregationFunction.equalsIgnoreCase("COUNT")) { +// st[index] = getCount(values); +// } else if (aggregationFunction.equalsIgnoreCase("AVG")) { +// st[index] = getAvg(values); +// } else if (aggregationFunction.equalsIgnoreCase("COUNT_DISTINCT")) { +// st[index] = getCountDistinct(values); +// } +// } else { +// st[index] = Double.NaN; +// } +// +// } +// result.add(toStringArray(st)); - } +// } return result; } + /** + * TODO + */ private String[] getTotalsOfColumns(int start, int length) { double[] st = new double[dataMatrix.length]; - for (int i = 0; i < dataMatrix.length; i++) { - for (int j = start; j < length + start; j++) { - try { - if (getCellType(i, j).equals(CellType.DATA)) { - String value = dataMatrix[i][j]; - if (!value.equals(DATA_MATRIX_NA)) { - st[i] = st[i] + new Double(value); - } - } - } catch (Exception e) { - logger.debug("Cant format the number " + (dataMatrix[i][j])); - } - } - } +// for (int i = 0; i < dataMatrix.length; i++) { +// for (int j = start; j < length + start; j++) { +// try { +// if (getCellType(i, j).equals(CellType.DATA)) { +// String value = dataMatrix[i][j]; +// if (!value.equals(DATA_MATRIX_NA)) { +// st[i] = st[i] + new Double(value); +// } +// } +// } catch (Exception e) { +// logger.debug("Cant format the number " + (dataMatrix[i][j])); +// } +// } +// } return toStringArray(st); } + /** + * TODO + */ private double getTotalsOfColumn(int column, CellType type) { double sum = 0; - int nrows = (type.getValue().equalsIgnoreCase("partialsum")) ? dataMatrix.length - 1 : dataMatrix.length; // if subtotal doesn't sum that partial total - for (int y = 0; y < nrows; y++) { - if (celltypeOfColumns.get(column).equals(type)) { - CellType prevCellType = getCellType(y,column-1); - String value = dataMatrix[y][column]; - if (!value.equals(DATA_MATRIX_NA)) { - sum = sum + new Double(value); - } - } - } +// int nrows = (type.getValue().equalsIgnoreCase("partialsum")) ? dataMatrix.length - 1 : dataMatrix.length; // if subtotal doesn't sum that partial total +// for (int y = 0; y < nrows; y++) { +// if (celltypeOfColumns.get(column).equals(type)) { +// CellType prevCellType = getCellType(y,column-1); +// String value = dataMatrix[y][column]; +// if (!value.equals(DATA_MATRIX_NA)) { +// sum = sum + new Double(value); +// } +// } +// } return sum; } + /** + * TODO + */ private String[] getTotalsOfColumnWithMeasure(int colunm) { double[] st = new double[measures.size()]; - int measurescount = 0; - - for (int y = 0; y < dataMatrix.length; y++) { - if (!celltypeOfRows.get(y).equals(CellType.CF)) { - st[measurescount % measures.size()] = st[measurescount % measures.size()] + new Double(dataMatrix[y][colunm]); - measurescount++; - } - } +// int measurescount = 0; +// +// for (int y = 0; y < dataMatrix.length; y++) { +// if (!celltypeOfRows.get(y).equals(CellType.CF)) { +// st[measurescount % measures.size()] = st[measurescount % measures.size()] + new Double(dataMatrix[y][colunm]); +// measurescount++; +// } +// } return toStringArray(st); } @@ -1860,39 +2072,45 @@ private int getSubtotalCellsNumber( List celltypeOfRows) { return toReturn; } + /** + * TODO + */ private double getTotalsOfRow(int row, CellType type) { double sum = 0; - int nSubtotals = getSubtotalCellsNumber(celltypeOfRows); - nSubtotals = (nSubtotals == 0) ? 0 : nSubtotals-1; - int nMaxCol = dataMatrix[0].length - (nSubtotals); - for (int y = 0; y < dataMatrix[0].length; y++) { -// if (y < celltypeOfRows.size() && celltypeOfRows.get(y).equals(type)) { //ORIG - if (y < celltypeOfRows.size() && celltypeOfRows.get(row).equals(type)) { - String value = dataMatrix[row][y]; -// if (!value.equals(DATA_MATRIX_NA)) { - if (nMaxCol <= 0 || (!value.equals(DATA_MATRIX_NA) && y < nMaxCol)) { //if maxcol <= 0 add always the value - sum = sum + new Double(value); - } - } - - } +// int nSubtotals = getSubtotalCellsNumber(celltypeOfRows); +// nSubtotals = (nSubtotals == 0) ? 0 : nSubtotals-1; +// int nMaxCol = dataMatrix[0].length - (nSubtotals); +// for (int y = 0; y < dataMatrix[0].length; y++) { +//// if (y < celltypeOfRows.size() && celltypeOfRows.get(y).equals(type)) { //ORIG +// if (y < celltypeOfRows.size() && celltypeOfRows.get(row).equals(type)) { +// String value = dataMatrix[row][y]; +//// if (!value.equals(DATA_MATRIX_NA)) { +// if (nMaxCol <= 0 || (!value.equals(DATA_MATRIX_NA) && y < nMaxCol)) { //if maxcol <= 0 add always the value +// sum = sum + new Double(value); +// } +// } +// +// } return sum; } + /** + * TODO + */ private String[] getTotalsOfRowWithMeasure(int row) { double[] st = new double[measures.size()]; - int measurescount = 0; - - for (int y = 0; y < dataMatrix[0].length; y++) { - if (!celltypeOfColumns.get(y).equals(CellType.CF)) { - String value = dataMatrix[row][y]; - if (!value.equals(DATA_MATRIX_NA)) { - st[measurescount % measures.size()] = st[measurescount % measures.size()] + new Double(value); - } - measurescount++; - } - } +// int measurescount = 0; +// +// for (int y = 0; y < dataMatrix[0].length; y++) { +// if (!celltypeOfColumns.get(y).equals(CellType.CF)) { +// String value = dataMatrix[row][y]; +// if (!value.equals(DATA_MATRIX_NA)) { +// st[measurescount % measures.size()] = st[measurescount % measures.size()] + new Double(value); +// } +// measurescount++; +// } +// } return toStringArray(st); } @@ -1995,7 +2213,6 @@ else if (!onRows && !this.config.optString("columntotalLabel").equals("")) } private void addTotals() throws JSONException { - Boolean rowsTotals = config.optBoolean("calculatetotalsoncolumns"); Boolean columnsTotals = config.optBoolean("calculatetotalsonrows"); @@ -2005,7 +2222,7 @@ private void addTotals() throws JSONException { if (rowsTotals) { rowsRoot.addChild(getHeaderTotalSubTree(measuresOnRow, rowsRoot.getSubTreeDepth() - 1, false)); - addCrosstabDataRow(dataMatrix.length, columnsSum, CellType.TOTAL); + addCrosstabDataRow(rowsRoot, dataMatrix.length, columnsSum, CellType.TOTAL); } if (columnsTotals) { @@ -2027,7 +2244,7 @@ private void addTotals() throws JSONException { } } columnsRoot.addChild(getHeaderTotalSubTree(!measuresOnRow, columnsRoot.getSubTreeDepth() - 1, true)); - addCrosstabDataColumns(dataMatrix[0].length, rowsSum, CellType.TOTAL); + addCrosstabDataColumns(rowsRoot, dataMatrix[0].length, rowsSum, CellType.TOTAL); } } @@ -2094,6 +2311,7 @@ public void addSubtotals() { } public int addSubtotalsToTheTreeNoMeasure(Node node, boolean horizontal, int startingPosition) { + int start = startingPosition; int length = node.getLeafsNumber(); String[] total; @@ -2109,14 +2327,16 @@ public int addSubtotalsToTheTreeNoMeasure(Node node, boolean horizontal, int sta List linesums = new ArrayList(); linesums.add(total); - addCrosstabDataLine(freshStartingPosition + node.getLeafsNumber(), linesums, horizontal, CellType.SUBTOTAL); + addCrosstabDataLine(node, freshStartingPosition + node.getLeafsNumber(), linesums, horizontal, CellType.SUBTOTAL); for (int i = 0; i < children.size(); i++) { - freshStartingPosition = addSubtotalsToTheTreeNoMeasure(children.get(i), horizontal, freshStartingPosition); + Node currChild = children.get(i); + freshStartingPosition = addSubtotalsToTheTreeNoMeasure(currChild, horizontal, freshStartingPosition); } Node totalNode = buildSubtotalNode(node.getSubTreeDepth() - 1, false, horizontal); node.addChild(totalNode); +// node.updateFathers(); return startingPosition + node.getLeafsNumber(); } return startingPosition + 1; @@ -2159,7 +2379,7 @@ public int addSubtotalsToTheNodeUpLevel(Node node, boolean horizontal, int start linesums.add(getTotals(linesToSum, horizontal)); } - addCrosstabDataLine(startingPosition, linesums, horizontal, CellType.SUBTOTAL); + addCrosstabDataLine(node, startingPosition, linesums, horizontal, CellType.SUBTOTAL); return startingPosition + measures.size(); } @@ -2207,7 +2427,7 @@ public int addSubtotalsToTheNodeFirstLevel(Node node, boolean horizontal, int po positionToAddNode = positionToAddNode + measuresCount * n.getChilds().size(); } node.addChild(subtotalNode); - addCrosstabDataLine(positionToAddNode, linesums, horizontal, CellType.SUBTOTAL); + addCrosstabDataLine(node, positionToAddNode, linesums, horizontal, CellType.SUBTOTAL); positionToAddNode = positionToAddNode + linesums.size(); } return positionToAddNode; @@ -2237,54 +2457,59 @@ else if (!horizontal && !this.config.optString("columnsubtotalLabel").equals("" toReturn.addChild(node); node = toReturn; } +// node.updateFathers(); return toReturn; } - // get totals just for subtotals columns + /** + * Get totals just for subtotals columns. + * + * TODO + */ private String[] getTotals(List lines, boolean horizontal) { double sum[]; if (!horizontal) { sum = new double[dataMatrix[0].length]; - for (int i = 0; i < dataMatrix[0].length; i++) { - String value = dataMatrix[lines.get(0)][i]; - if (!value.equals(DATA_MATRIX_NA) && - (getCellType(lines.get(0), i).equals(CellType.DATA) || getCellType(lines.get(0), i).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal - sum[i] = new Double(value); - } - } - for (int j = 1; j < lines.size(); j++) { - for (int i = 0; i < dataMatrix[0].length; i++) { - String value = dataMatrix[lines.get(j)][i]; -// if (!value.equals(DATA_MATRIX_NA) && (getCellType(lines.get(j), i).equals(CellType.DATA))) { - if (!value.equals(DATA_MATRIX_NA) && - (getCellType(lines.get(j), i).equals(CellType.DATA)|| getCellType(lines.get(j), i).equals(CellType.SUBTOTAL))) { - sum[i] = sum[i] + new Double(value); - } - } - } +// for (int i = 0; i < dataMatrix[0].length; i++) { +// String value = dataMatrix[lines.get(0)][i]; +// if (!value.equals(DATA_MATRIX_NA) && +// (getCellType(lines.get(0), i).equals(CellType.DATA) || getCellType(lines.get(0), i).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal +// sum[i] = new Double(value); +// } +// } +// for (int j = 1; j < lines.size(); j++) { +// for (int i = 0; i < dataMatrix[0].length; i++) { +// String value = dataMatrix[lines.get(j)][i]; +//// if (!value.equals(DATA_MATRIX_NA) && (getCellType(lines.get(j), i).equals(CellType.DATA))) { +// if (!value.equals(DATA_MATRIX_NA) && +// (getCellType(lines.get(j), i).equals(CellType.DATA)|| getCellType(lines.get(j), i).equals(CellType.SUBTOTAL))) { +// sum[i] = sum[i] + new Double(value); +// } +// } +// } } else { sum = new double[dataMatrix.length]; - for (int i = 0; i < dataMatrix.length; i++) { - String value = dataMatrix[i][lines.get(0)]; -// if (!value.equals(DATA_MATRIX_NA) && (getCellType(i, lines.get(0)).equals(CellType.DATA))) { // ORIG - if (!value.equals(DATA_MATRIX_NA) && - (getCellType(i, lines.get(0)).equals(CellType.DATA) || getCellType(i, lines.get(0)).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal - sum[i] = new Double(value); - } - } - int startJ = 1; - for (int j = startJ; j < lines.size(); j++) { - for (int i = 0; i < dataMatrix.length; i++) { - String value = dataMatrix[i][lines.get(j)]; -// if (!value.equals(DATA_MATRIX_NA) && (getCellType(i, lines.get(j)).equals(CellType.DATA))) { - if (!value.equals(DATA_MATRIX_NA) && - (getCellType(i, lines.get(j)).equals(CellType.DATA) || getCellType(i, lines.get(j)).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal - sum[i] = sum[i] + new Double(value); - } - - } - } +// for (int i = 0; i < dataMatrix.length; i++) { +// String value = dataMatrix[i][lines.get(0)]; +//// if (!value.equals(DATA_MATRIX_NA) && (getCellType(i, lines.get(0)).equals(CellType.DATA))) { // ORIG +// if (!value.equals(DATA_MATRIX_NA) && +// (getCellType(i, lines.get(0)).equals(CellType.DATA) || getCellType(i, lines.get(0)).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal +// sum[i] = new Double(value); +// } +// } +// int startJ = 1; +// for (int j = startJ; j < lines.size(); j++) { +// for (int i = 0; i < dataMatrix.length; i++) { +// String value = dataMatrix[i][lines.get(j)]; +//// if (!value.equals(DATA_MATRIX_NA) && (getCellType(i, lines.get(j)).equals(CellType.DATA))) { +// if (!value.equals(DATA_MATRIX_NA) && +// (getCellType(i, lines.get(j)).equals(CellType.DATA) || getCellType(i, lines.get(j)).equals(CellType.SUBTOTAL))) { //get SUBTOTAL too for grand-subtotal +// sum[i] = sum[i] + new Double(value); +// } +// +// } +// } } return toStringArray(sum); @@ -2300,12 +2525,14 @@ private String[] getTotals(List lines, boolean horizontal) { * @param i * the id of the column to get * @return the i-th column of the data matrix + * + * TODO */ private String[] getCrosstabDataColumn(int i) { String[] column = new String[dataMatrix.length]; - for (int j = 0; j < dataMatrix.length; j++) { - column[j] = dataMatrix[j][i]; - } +// for (int j = 0; j < dataMatrix.length; j++) { +// column[j] = dataMatrix[j][i]; +// } return column; } @@ -2317,7 +2544,17 @@ private String[] getCrosstabDataColumn(int i) { * @return the i-th row of the data matrix */ private String[] getCrosstabDataRow(int i) { - return dataMatrix[i]; + String[] ret = null; + + int length = dataMatrix[i].length; + + ret = new String[length]; + + for(int j = 0; j line, boolean horizontal, CellType type) { + public void addCrosstabDataLine(Node currNode, int startposition, List line, boolean horizontal, CellType type) { if (horizontal) { - addCrosstabDataColumns(startposition, line, type); + addCrosstabDataColumns(currNode, startposition, line, type); } else { - addCrosstabDataRow(startposition, line, type); + addCrosstabDataRow(currNode, startposition, line, type); } } @@ -2350,25 +2587,50 @@ public void addCrosstabDataLine(int startposition, List line, boolean * @param type * the type of the data */ - public void addCrosstabDataColumns(int startposition, List colums, CellType type) { + public void addCrosstabDataColumns(Node currNode, int startposition, List colums, CellType type) { Assert.assertNotNull(dataMatrix, "The data matrix must not be null"); Assert.assertTrue(startposition <= dataMatrix[0].length, "The position you want to add the columns is bigger than the table size ts=" + dataMatrix[0].length + " position= " + startposition); - String[][] newData = new String[dataMatrix.length][dataMatrix[0].length + colums.size()]; + + final List measures = getMeasures(); + final int measureSize = measures.size(); + final int rowsToAddSize = colums.isEmpty() ? 0 : colums.get(0).length; + final int colsToAddSize = colums.size(); + + Placeholder/**/[][] newData = new Placeholder[dataMatrix.length][]; + for (int i=0; i*/[dataMatrix[0].length + colums.size()]; + } + int columnsToAddSize = colums.size(); for (int i = 0; i < dataMatrix.length; i++) { + + // Add the column before the new one for (int x = 0; x < startposition; x++) { newData[i][x] = dataMatrix[i][x]; } + // Add the new column for (int x = 0; x < columnsToAddSize; x++) { - newData[i][startposition + x] = colums.get(x)[i]; + Placeholder/**/ newPlaceholder = null; + int index = (!measuresOnRow) ? x % measureSize : i % measureSize; + MeasureInfo measureInfo = measures.get(index); + + Node currRow = this.rowsRoot.getLeafs().get(i); + Node currCol = currNode; + String path = createJsonPathQueryFromNodes(currRow, currCol, measureInfo); + newPlaceholder = new JsonPathAggregatorPlaceholder(this, measureInfo, getAggregatorDelegate(measureInfo), type, path); + + newData[i][startposition + x] = newPlaceholder; } + // Add the column after the new one for (int x = 0; x < dataMatrix[0].length - startposition; x++) { newData[i][startposition + columnsToAddSize + x] = dataMatrix[i][startposition + x]; } + } + // update the list of columns type for (int i = 0; i < colums.size(); i++) { celltypeOfColumns.add(i + startposition, type); @@ -2426,30 +2688,54 @@ public void addCrosstabDataColumns(int startposition, List colums, Cel * @param type * the type of the data */ - public void addCrosstabDataRow(int startposition, List rows, CellType type) { + public void addCrosstabDataRow(Node currNode, int startposition, List rows, CellType type) { Assert.assertNotNull(dataMatrix, "The data matrix must not be null"); Assert.assertTrue(startposition <= dataMatrix.length, "The position you want to add the rows is bigger than the table size ts=" + dataMatrix[0].length + " position= " + startposition); - String[][] newData = new String[dataMatrix.length + rows.size()][]; - int rowsToAddSize = rows.size(); + final List measures = getMeasures(); + final int measureSize = measures.size(); + final int rowsToAddSize = rows.size(); + final int colsToAddSize = rows.isEmpty() ? 0 : rows.get(0).length; + Placeholder/**/[][] newData = new Placeholder[dataMatrix.length + rows.size()][]; + for (int i=0; i<(dataMatrix.length + rows.size()); i++) { + newData[i] = new Placeholder/**/[rows.get(0).length]; + } + + // Add rows before the new one for (int x = 0; x < startposition; x++) { newData[x] = dataMatrix[x]; } + // Add the new rows for (int x = 0; x < rowsToAddSize; x++) { - newData[startposition + x] = rows.get(x); + newData[startposition + x] = new Placeholder/**/[colsToAddSize]; + for (int j = 0; j < colsToAddSize; j++) { + Placeholder/**/ newPlaceholder = null; + int index = j /* % measureSize */; + MeasureInfo measureInfo = measures.get(!measuresOnRow ? j % measureSize : x); + + Node currRow = currNode; + Node currCol = this.columnsRoot.getLeafs().get(index); + String path = createJsonPathQueryFromNodes(currRow, currCol, measureInfo); + newPlaceholder = new JsonPathAggregatorPlaceholder(this, measureInfo, getAggregatorDelegate(measureInfo), type, path); + + newData[startposition + x][j] = newPlaceholder; + } } + // Add rows after the new one for (int x = 0; x < dataMatrix.length - startposition; x++) { newData[startposition + rowsToAddSize + x] = dataMatrix[startposition + x]; } - // update the list of rows type + + // Update the list of rows type for (int i = 0; i < rows.size(); i++) { celltypeOfRows.add(i + startposition, type); } + // Replace the original matrix dataMatrix = newData; if (type.equals(CellType.SUBTOTAL)) { @@ -2517,8 +2803,24 @@ public Node getRowsRoot() { return rowsRoot; } + /** + * TODO + */ public String[][] getDataMatrix() { - return dataMatrix; + String[][] ret = null; + + int rowsCount = dataMatrix.length; + int colsCount = dataMatrix[0].length; + + ret = new String[rowsCount][colsCount]; + + for (int row = 0; row < rowsCount; row++) { + for (int col = 0; col < colsCount; col++) { + ret[row][col] = dataMatrix[row][col].getValueAsString(); + } + } + + return ret; } public List getRowCordinates() { @@ -2679,28 +2981,28 @@ public List getCelltypeOfColumns() { return celltypeOfColumns; } - /** - * @param celltypeOfColumns - * the celltypeOfColumns to set - */ - public void setCelltypeOfColumns(List celltypeOfColumns) { - this.celltypeOfColumns = celltypeOfColumns; - } - - /** - * @return the celltypeOfRows - */ - public List getCelltypeOfRows() { - return celltypeOfRows; - } - - /** - * @param celltypeOfRows - * the celltypeOfRows to set - */ - public void setCelltypeOfRows(List celltypeOfRows) { - this.celltypeOfRows = celltypeOfRows; - } +// /** +// * @param celltypeOfColumns +// * the celltypeOfColumns to set +// */ +// public void setCelltypeOfColumns(List celltypeOfColumns) { +// this.celltypeOfColumns = celltypeOfColumns; +// } +// +// /** +// * @return the celltypeOfRows +// */ +// public List getCelltypeOfRows() { +// return celltypeOfRows; +// } +// +// /** +// * @param celltypeOfRows +// * the celltypeOfRows to set +// */ +// public void setCelltypeOfRows(List celltypeOfRows) { +// this.celltypeOfRows = celltypeOfRows; +// } public boolean isMeasureOnRow() { try { @@ -2823,4 +3125,19 @@ private int getColumnIndex(String columnLabel, List measuresHeaderList) { } return toReturn; } + + /** + * @return the parsedValuesDataStore + */ + public DocumentContext getParsedValuesDataStore() { + return parsedValuesDataStore; + } + + /** + * @return the countMeasures + */ + public List getCountMeasures() { + return countMeasures; + } + } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTabHTMLSerializer.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTabHTMLSerializer.java index 933bf299359..c8237ff955d 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTabHTMLSerializer.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/CrossTabHTMLSerializer.java @@ -380,7 +380,7 @@ private SourceBean serializeColumnsHeaders(CrossTab crossTab) throws SourceBeanE Column columnObj = ((Column) getCategoryConfByLabel(crossTab, crossTab.getColumnsRoot().getLevel(i).get(0).getValue(), "columns")); String columnName = (columnObj != null) ? columnObj.getEntityId() : ""; - aColumn.setAttribute(NG_CLICK_ATTRIBUTE, "selectRow('" + crossTab.getColumnsRoot().getLevel(i).get(0).getValue() + "','" + aColumn.setAttribute(NG_CLICK_ATTRIBUTE, "selectRow('" + columnName + "','" + StringEscapeUtils.escapeJavaScript(text) + "')"); } if (crossTab.getCrosstabDefinition().isMeasuresOnColumns() && i + 2 == levels) { @@ -781,7 +781,7 @@ private SourceBean serializeData(CrossTab crossTab) throws SourceBeanException, String rowHeaders = ""; String measureRef = ""; if (crossTab.getRowsSpecification().size() > 0) { - List rowsDef = crossTab.getRowsHeaderList(); + List rowsDef = crossTab.getRowsHeaderIdList(); for (int r = 0; r < rowsDef.size(); r++) { rowHeaders += crossTab.PATH_SEPARATOR + rowsDef.get(r); } @@ -820,7 +820,7 @@ private SourceBean serializeData(CrossTab crossTab) throws SourceBeanException, String columnsHeaders = ""; if (columnsSpecification.size() > 0) { - List columnsDef = crossTab.getColumnsHeaderList(); + List columnsDef = crossTab.getColumnsHeaderIdList(); for (int c = 0; c < columnsDef.size(); c++) { columnsHeaders += crossTab.PATH_SEPARATOR + columnsDef.get(c); } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/Node.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/Node.java index 56d4746802a..e1f079d977c 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/Node.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/Node.java @@ -37,9 +37,12 @@ public class Node implements Cloneable, Comparable { public static final String CROSSTAB_NODE_JSON_CHILDS = "node_childs"; public static final String CROSSTAB_NODE_JSON_KEY = "node_key"; public static final String CROSSTAB_NODE_JSON_DESCRIPTION = "node_description"; + public static final String CROSSTAB_NODE_JSON_COLUMN = "node_column"; + private String columnName = null;// column name private final String value;// the value of the node private final String description;// the description of the node + private final boolean measure; private CellType cellType;// the type of the node private List childs;// list of childs private int leafPosition = -1;// position of the leafs in the tree.. If this @@ -55,17 +58,49 @@ public class Node implements Cloneable, Comparable { private Node fatherNode; // != from null only if we need the value private Integer distanceFromRoot; + private final JSONObject jsonObject; public Node(String value) { this.value = value; this.description = value; + measure = false; childs = new ArrayList(); + jsonObject = null; } public Node(String value, String description) { this.value = value; this.description = description; + measure = false; childs = new ArrayList(); + jsonObject = null; + } + + public Node(String columnName, String value, String description) { + this.columnName = columnName; + this.value = value; + this.description = description; + measure = false; + childs = new ArrayList(); + jsonObject = null; + } + + public Node(String columnName, String value, String description, boolean measure) { + this.columnName = columnName; + this.value = value; + this.description = description; + this.measure = measure; + childs = new ArrayList(); + jsonObject = null; + } + + public Node(String columnName, String value, String description, JSONObject jsonObject) { + this.columnName = columnName; + this.value = value; + this.description = description; + this.measure = false; + childs = new ArrayList(); + this.jsonObject = jsonObject; } public String getValue() { @@ -76,6 +111,13 @@ public String getDescription() { return description; } + /** + * @return the jsonObject + */ + public JSONObject getJsonObject() { + return jsonObject; + } + public Node getParentNode() { return this.fatherNode; @@ -92,6 +134,7 @@ public void setChilds(List childs) { public void addOrderedChild(Node child) { childs.add(child); + child.fatherNode = this; if (childs != null) { Collections.sort(childs); } @@ -99,7 +142,7 @@ public void addOrderedChild(Node child) { public void addOrderedChild(Node child, Comparator comp) { childs.add(child); - + child.fatherNode = this; if (childs != null) { if (comp == null) Collections.sort(childs); @@ -110,6 +153,7 @@ public void addOrderedChild(Node child, Comparator comp) { public void addChild(Node child) { childs.add(child); + child.fatherNode = this; } public boolean isChild(Node child) { @@ -142,6 +186,7 @@ public int getLeafsNumber() { public JSONObject toJSONObject() throws JSONException { JSONObject thisNode = new JSONObject(); + thisNode.put(CROSSTAB_NODE_JSON_COLUMN, this.columnName); thisNode.put(CROSSTAB_NODE_JSON_KEY, this.value); thisNode.put(CROSSTAB_NODE_JSON_DESCRIPTION, this.description); @@ -285,15 +330,15 @@ public List getLeafs() { return list; } - /** - * Update the fathers of this tree - */ - public void updateFathers() { - for (int i = 0; i < childs.size(); i++) { - childs.get(i).fatherNode = this; - childs.get(i).updateFathers(); - } - } +// /** +// * Update the fathers of this tree +// */ +// public void updateFathers() { +// for (int i = 0; i < childs.size(); i++) { +// childs.get(i).fatherNode = this; +// childs.get(i).updateFathers(); +// } +// } public int getSubTreeDepth() { if (childs.size() == 0) { @@ -333,7 +378,7 @@ public int getRightMostLeafPositionCF() { */ @Override public Node clone() { - Node n = new Node(value, description); + Node n = new Node(columnName, value, description, measure); if (childs.size() > 0) { for (int j = 0; j < childs.size(); j++) { n.addChild(childs.get(j).clone()); @@ -347,9 +392,9 @@ public String toString() { String string; if (childs.size() == 0) { - return "[V:" + value.toString() + "-D:" + description + "]"; + return "[C:" + String.valueOf(columnName) + "-V:" + value.toString() + "-D:" + description + "]"; } else { - string = "[V:" + value.toString() + "-D:" + description + ",["; + string = "[C:" + String.valueOf(columnName) + "-V:" + value.toString() + "-D:" + description + ",["; for (int i = 0; i < childs.size() - 1; i++) { string = string + childs.get(i).toString() + ","; } @@ -452,4 +497,29 @@ public void orderedSubtree(Map sortKeys) { } } + public String getPath() { + return getPath(this); + } + + private String getPath(Node node) { + StringBuilder sb = new StringBuilder(); + + if (node.fatherNode != null) { + sb.append(getPath(node.fatherNode)) + .append("/"); + } + + sb.append("[C:" + String.valueOf(columnName) + "-V:" + node.value.toString() + "-D:" + node.description + "]"); + + return sb.toString(); + } + + public String getColumnName() { + return columnName; + } + + public boolean isMeasure() { + return measure; + } + } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/NodeComparator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/NodeComparator.java index cd2fe4db4c7..ae265e14f80 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/NodeComparator.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/NodeComparator.java @@ -17,7 +17,11 @@ */ package it.eng.knowage.engine.cockpit.api.crosstable; +import java.text.SimpleDateFormat; import java.util.Comparator; +import java.util.Date; + +import org.json.JSONObject; /** * @authors Alberto Ghedin (alberto.ghedin@eng.it) @@ -55,15 +59,34 @@ public NodeComparator(int direction) { @Override public int compare(Node arg0, Node arg1) { + String value0 = arg0.getValue(); + String value1 = arg1.getValue(); try { - // compares only on values - Float arg0Value = new Float(arg0.getValue()); - Float arg1Value = new Float(arg1.getValue()); - return direction * arg0Value.compareTo(arg1Value); + /* + * Here we can consider only one node + * because the second one has the same + * configuration, obviously. + */ + JSONObject jsonObject = arg0.getJsonObject(); + String type = jsonObject.getString("type"); + if ("string".equals(type)) { + return direction * value0.compareTo(value1); + } else if ("date".equals(type)) { + String pattern = jsonObject.getString("dateFormatJava"); + SimpleDateFormat sdf = new SimpleDateFormat(pattern); + Date date0 = sdf.parse(value0); + Date date1 = sdf.parse(value1); + return direction * date0.compareTo(date1); + } else { + // compares only on values + Float arg0Value = new Float(value0); + Float arg1Value = new Float(value1); + return direction * arg0Value.compareTo(arg1Value); + } } catch (Exception e) { // if its not possible to convert the values in float, consider them // as strings - return direction * arg0.getValue().compareTo(arg1.getValue()); + return direction * value0.compareTo(value1); } } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AggregatorDelegate.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AggregatorDelegate.java new file mode 100644 index 00000000000..d4b05eaca7b --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AggregatorDelegate.java @@ -0,0 +1,32 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.util.List; + +/** + * Interface for an aggregator delegate. + * + * @author Marco Libanori + */ +public interface AggregatorDelegate { + + Double aggregate(final List values); + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AverageAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AverageAggregator.java new file mode 100644 index 00000000000..dde683ee268 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/AverageAggregator.java @@ -0,0 +1,58 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.math.BigDecimal; +import java.util.List; + +/** + * Singleton of an avg aggregator. + * + * @author Marco Libanori + * + */ +public class AverageAggregator implements AggregatorDelegate { + + private static final AggregatorDelegate instance = new AverageAggregator(); + + protected AverageAggregator() { + + } + + public static AggregatorDelegate instance() { + return instance; + } + + @Override + public Double aggregate(List values) { + double ret = 0.0; + double weightSum = 0.0; + if (!values.isEmpty()) { + for (ValueWithWeightPlaceholder currPlaceholder : values) { + Double value = currPlaceholder.getValue(); + Double weight = currPlaceholder.getWeight(); + ret += (value * weight); + weightSum += weight; + } + ret = BigDecimal.valueOf(ret / weightSum).setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue(); + } + return ret; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/CountAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/CountAggregator.java new file mode 100644 index 00000000000..20e83c7e497 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/CountAggregator.java @@ -0,0 +1,35 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +/** + * Singleton of a count aggregator. + * + * @author Marco Libanori + * + */ +public class CountAggregator extends SumAggregator { + + private static final AggregatorDelegate instance = new CountAggregator(); + + public static AggregatorDelegate instance() { + return instance; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/JsonPathAggregatorPlaceholder.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/JsonPathAggregatorPlaceholder.java new file mode 100644 index 00000000000..2b8cbebfcc6 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/JsonPathAggregatorPlaceholder.java @@ -0,0 +1,162 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.apache.log4j.Logger; + +import com.jayway.jsonpath.DocumentContext; + +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab; +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.CellType; +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.MeasureInfo; + +/** + * Placeholder for values that are results of some aggregations. + * + * @author Marco Libanori + */ +public class JsonPathAggregatorPlaceholder implements Placeholder { + + private static Logger logger = Logger.getLogger(JsonPathAggregatorPlaceholder.class); + + final CrossTab crossTab; + final MeasureInfo measure; + final AggregatorDelegate delegate; + final CellType cellType; + final String path; + final DocumentContext parsedValuesDataStore; + + public JsonPathAggregatorPlaceholder( + final CrossTab crossTab, + final MeasureInfo measure, + final AggregatorDelegate delegate, + final CellType cellType, + final String path) { + + this.crossTab = crossTab; + this.parsedValuesDataStore = crossTab.getParsedValuesDataStore(); + this.measure = measure; + this.delegate = delegate; + this.cellType = cellType; + this.path = path; + } + + @Override + public final String getValueAsString() { + Double currValue = getValue(); + return /* path + " - " + */ (currValue != null ? getValue().toString() : ""); + } + + private void filterNullValues(List values) { + Iterator iterator = values.iterator(); + while (iterator.hasNext()) { + ValueWithWeightPlaceholder next = iterator.next(); + if (next.getValue() == null) { + iterator.remove(); + } + } + } + + + @Override + public final Double getValue() { + try { + final List values = selectValues(); + + filterNullValues(values); + + return delegate.aggregate(values); + } catch (Exception e) { + logger.error("Error during aggregation at path \"" + path + "\"", e); + throw e; + } + } + + @Override + public String toString() { + return "JsonPathAggregatorPlaceholder [path=" + path + "]"; + } + + private List selectValues() { + List ret = new ArrayList(); + Object read = parsedValuesDataStore.read(path); + if (read instanceof net.minidev.json.JSONArray) { + net.minidev.json.JSONArray coll = (net.minidev.json.JSONArray) read; + for (int i = 0; i currObject = (Map) object; + + Iterator> iterator = currObject.entrySet().iterator(); + value = String.valueOf(iterator.next().getValue()); + if (iterator.hasNext()) { + weight = String.valueOf(iterator.next().getValue()); + } + } else { + throw new IllegalStateException("Cannot manage type " + object.getClass()); + } + + ret.add(new ValueWithWeightPlaceholder(value, weight, measure)); + } + } + return ret; + } + + @Override + public MeasureInfo getMeasureInfo() { + return measure; + } + + @Override + public CellType getCellType() { + return cellType; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean isAggregation() { + return true; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MaxAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MaxAggregator.java new file mode 100644 index 00000000000..3e46a3f4fc7 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MaxAggregator.java @@ -0,0 +1,52 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Singleton of a max aggregator. + * + * @author Marco Libanori + * + */ +public class MaxAggregator implements AggregatorDelegate { + + private static final AggregatorDelegate instance = new MaxAggregator(); + + protected MaxAggregator() { + + } + + public static AggregatorDelegate instance() { + return instance; + } + + @Override + public Double aggregate(List values) { + List altList = new ArrayList(); + for (Placeholder currPlaceholder : values) { + altList.add(currPlaceholder.getValue()); + } + return altList.isEmpty() ? null : Collections.max(altList); + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MinAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MinAggregator.java new file mode 100644 index 00000000000..bfffc364e66 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/MinAggregator.java @@ -0,0 +1,52 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Singleton of a min aggregator. + * + * @author Marco Libanori + * + */ +public class MinAggregator implements AggregatorDelegate { + + private static final AggregatorDelegate instance = new MinAggregator(); + + protected MinAggregator() { + + } + + public static AggregatorDelegate instance() { + return instance; + } + + @Override + public Double aggregate(List values) { + List altList = new ArrayList(); + for (Placeholder currPlaceholder : values) { + altList.add(currPlaceholder.getValue()); + } + return altList.isEmpty() ? null : Collections.min(altList); + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotAvailablePlaceholder.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotAvailablePlaceholder.java new file mode 100644 index 00000000000..a0563b4054f --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotAvailablePlaceholder.java @@ -0,0 +1,67 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.CellType; +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.MeasureInfo; + +/** + * Dummy placeholder to be used when there isn't no value for a certain cell. + * + * @author Marco Libanori + * + */ +public class NotAvailablePlaceholder implements Placeholder { + + @Override + public Double getValue() { + return null; + } + + @Override + public MeasureInfo getMeasureInfo() { + throw new UnsupportedOperationException("Not intended to be called"); + } + + @Override + public String toString() { + return getValueAsString(); + } + + @Override + public String getValueAsString() { + return ""; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public boolean isAggregation() { + return false; + } + + @Override + public CellType getCellType() { + return CellType.DATA; + } + +} \ No newline at end of file diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotDefinedAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotDefinedAggregator.java new file mode 100644 index 00000000000..c6999ffc592 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/NotDefinedAggregator.java @@ -0,0 +1,46 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.util.List; + +/** + * Singleton of a n.d. aggregator. + * + * @author Marco Libanori + * + */ +public class NotDefinedAggregator implements AggregatorDelegate { + + private static final AggregatorDelegate instance = new NotDefinedAggregator(); + + protected NotDefinedAggregator() { + + } + + public static AggregatorDelegate instance() { + return instance; + } + + @Override + public Double aggregate(List values) { + return null; + } + +} diff --git a/knowage/src/main/webapp/themes/geobi/css/domain/domain.css b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/Placeholder.java similarity index 55% rename from knowage/src/main/webapp/themes/geobi/css/domain/domain.css rename to knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/Placeholder.java index 478a1946f33..19453a2697c 100644 --- a/knowage/src/main/webapp/themes/geobi/css/domain/domain.css +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/Placeholder.java @@ -1,31 +1,37 @@ /* * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. - * + * Knowage 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 Affero General Public License for more details. - * + * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - */ + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.CellType; +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.MeasureInfo; + +/** + * Placeholder interface for the data matrix into the crosstab. + * + * @author Marco Libanori + */ +public interface Placeholder { + Double getValue(); + String getValueAsString(); + MeasureInfo getMeasureInfo(); + CellType getCellType(); + boolean isAvailable(); + boolean isAggregation(); -/******************************************************************************************************* - * Model Structure - ********************************************************************************************************/ - -.icon-domain-delete { - background-image:url(../../img/domain/erase.png) !important; -} -.icon-domain-add { - background-image:url(../../img/domain/attach.png) !important; -} -.icon-domain-filter { - background-image:url(../../img/domain/filter.gif) !important; } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/SumAggregator.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/SumAggregator.java new file mode 100644 index 00000000000..5024c43545a --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/SumAggregator.java @@ -0,0 +1,50 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import java.util.List; + +/** + * Singleton of a sum aggregator. + * + * @author Marco Libanori + * + */ +public class SumAggregator implements AggregatorDelegate { + + private static final AggregatorDelegate instance = new SumAggregator(); + + protected SumAggregator() { + + } + + public static AggregatorDelegate instance() { + return instance; + } + + @Override + public Double aggregate(List values) { + double ret = 0.0; + for (Placeholder currPlaceholder : values) { + ret += currPlaceholder.getValue(); + } + return ret; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValuePlaceholder.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValuePlaceholder.java new file mode 100644 index 00000000000..7d9ed0774eb --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValuePlaceholder.java @@ -0,0 +1,73 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.CellType; +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.MeasureInfo; + +/** + * Placeholder for existing and certain value. + * + * @author Marco Libanori + */ +public class ValuePlaceholder implements Placeholder { + private Double value; + private MeasureInfo measureInfo; + + public ValuePlaceholder(final String value, final MeasureInfo measureInfo) { + this.value = value != null && !"".equals(value) ? Double.valueOf(value) : null; + this.measureInfo = measureInfo; + } + + @Override + public Double getValue() { + return value; + } + + @Override + public MeasureInfo getMeasureInfo() { + return measureInfo; + } + + @Override + public String toString() { + return getValueAsString(); + } + + @Override + public String getValueAsString() { + return value != null ? value.toString() : ""; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public boolean isAggregation() { + return false; + } + + @Override + public CellType getCellType() { + return CellType.DATA; + } + +} \ No newline at end of file diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValueWithWeightPlaceholder.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValueWithWeightPlaceholder.java new file mode 100644 index 00000000000..77a1716a446 --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/crosstable/placeholder/ValueWithWeightPlaceholder.java @@ -0,0 +1,42 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.engine.cockpit.api.crosstable.placeholder; + +import it.eng.knowage.engine.cockpit.api.crosstable.CrossTab.MeasureInfo; + +/** + * @author Marco Libanori + */ +class ValueWithWeightPlaceholder extends ValuePlaceholder { + + private final Double weight; + + public ValueWithWeightPlaceholder(String value, String weight, MeasureInfo measureInfo) { + super(value, measureInfo); + this.weight = Double.valueOf(weight); + } + + /** + * @return the weight + */ + public Double getWeight() { + return weight; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/engine/EngineResource.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/engine/EngineResource.java index 0517beeb640..0765657e245 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/engine/EngineResource.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/engine/EngineResource.java @@ -17,6 +17,7 @@ */ package it.eng.knowage.engine.cockpit.api.engine; +import static it.eng.spagobi.commons.constants.SpagoBIConstants.CREATE_CUSTOM_CHART; import static it.eng.spagobi.commons.constants.SpagoBIConstants.DISCOVERY_WIDGET_USE; import static it.eng.spagobi.commons.constants.SpagoBIConstants.DOCUMENT_WIDGET_USE; import static it.eng.spagobi.commons.constants.SpagoBIConstants.EDIT_PYTHON_SCRIPTS; @@ -161,6 +162,9 @@ public List getEngine() throws EMFInternalError { if (functionalities.contains(EDIT_PYTHON_SCRIPTS)) { ret.add(Widget.builder().withName("Python").withDescKey("sbi.cockpit.editor.newwidget.description.python").withImg("10.png") .withCssClass("fab fa-python").withType("python").withTag("python").build()); + + ret.add(Widget.builder().withName("r").withDescKey("sbi.cockpit.editor.newwidget.description.R").withImg("11.png").withCssClass("fab fa-r-project") + .withType("r").withTag("r").build()); } if (functionalities.contains(DISCOVERY_WIDGET_USE)) { @@ -168,6 +172,10 @@ public List getEngine() throws EMFInternalError { ret.add(Widget.builder().withName("Discovery").withDescKey("sbi.cockpit.editor.newwidget.description.discovery")/* TODO : .withImg(???) */ .withCssClass("fa fa-rocket").withType("discovery").withTag("discovery").build()); } + if (functionalities.contains(CREATE_CUSTOM_CHART)) { + ret.add(Widget.builder().withName("Custom Chart").withDescKey("sbi.cockpit.editor.newwidget.description.custom.chart").withImg("4.png") + .withCssClass("fas fa-bezier-curve").withType("customchart").withTag("customChart").build()); + } return ret; } diff --git a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java index 2113b34ba75..adccdfb0174 100644 --- a/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java +++ b/knowagecockpitengine/src/main/java/it/eng/knowage/engine/cockpit/api/export/excel/ExcelExporter.java @@ -85,6 +85,7 @@ public class ExcelExporter { private final Map i18nMessages; private final Map actualSelectionMap; + private final Map associativeToDatasetParametersMap; private final boolean exportWidget; @@ -109,6 +110,7 @@ public ExcelExporter(String outputType, String userUniqueIdentifier, Map(); + this.associativeToDatasetParametersMap = new HashMap<>(); } public ExcelExporter(String outputType, String userUniqueIdentifier, JSONObject body) { @@ -128,6 +130,7 @@ public ExcelExporter(String outputType, String userUniqueIdentifier, JSONObject this.actualSelectionMap = new HashMap<>(); this.parameterMap = new HashMap<>(); + this.associativeToDatasetParametersMap = new HashMap<>(); } private boolean setExportWidget(JSONObject body) { @@ -465,6 +468,7 @@ private JSONObject getDataStoreForWidget(JSONObject template, JSONObject widget) } datastore.put("widgetData", widget); + datastore.put("cocpitSelectionAggregations", cockpitSelections.get("aggregations")); JSONObject content = widget.optJSONObject("content"); String widgetName = null; if (widget.has("style")) { @@ -490,6 +494,10 @@ private JSONObject getDataStoreForWidget(JSONObject template, JSONObject widget) private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetName) throws JSONException, SerializationException { CreationHelper createHelper = wb.getCreationHelper(); + JSONArray widgetsMapAggregations = new JSONArray(); + if (body.has("widgetsMapAggregations")) { + widgetsMapAggregations = body.getJSONArray("widgetsMapAggregations"); + } if (dataStore.has("widgetType") && dataStore.getString("widgetType").equalsIgnoreCase("[\"static-pivot-table\"]")) { @@ -546,33 +554,14 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam JSONArray columns = metadata.getJSONArray("fields"); columns = filterDataStoreColumns(columns); JSONArray rows = dataStore.getJSONArray("rows"); + JSONObject columnsAggregations = new JSONObject(); + if (dataStore.has("cocpitSelectionAggregations")) { + columnsAggregations = dataStore.getJSONObject("cocpitSelectionAggregations"); + } - Sheet sheet; - Row header = null; - if (exportWidget) { - widgetName = WorkbookUtil.createSafeSheetName(widgetName); - sheet = wb.createSheet(widgetName); + HashMap mapColumnsAggregations = getMapFromAggregations(columnsAggregations); - // Create HEADER - Column Names - header = sheet.createRow((short) 0); // first row - } else { - String sheetName = "empty"; - if (dataStore.has("widgetName") && dataStore.getString("widgetName") != null && !dataStore.getString("widgetName").isEmpty()) { - if (dataStore.has("sheetInfo")) { - sheetName = dataStore.getString("sheetInfo").concat(".").concat(widgetName); - } else { - sheetName = widgetName; - } - } - - sheetName = WorkbookUtil.createSafeSheetName(sheetName); - sheet = wb.createSheet(sheetName); - // First row for Widget name in case exporting whole Cockpit document - Row firstRow = sheet.createRow((short) 0); - Cell firstCell = firstRow.createCell(0); - firstCell.setCellValue(widgetName); - header = sheet.createRow((short) 1); - } + Sheet sheet; JSONObject widgetData = dataStore.getJSONObject("widgetData"); @@ -611,9 +600,24 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam } + if (widgetsMapAggregations != null && !widgetsMapAggregations.isNull(0)) { + + JSONArray aggrNewVar = (JSONArray) widgetsMapAggregations.getJSONObject(0).get("columnSelectedOfDataset"); + mapColumnsAggregations = getMapFromAggregationsFromArray(aggrNewVar); + + } + // column.header matches with name or alias // Fill Header JSONArray columnsOrdered = new JSONArray(); + JSONArray groupsArray = new JSONArray(); + if (widgetData.has("groups")) { + groupsArray = widgetData.getJSONArray("groups"); + } + HashMap mapGroupsAndColumns = new HashMap(); + + HashMap headerToAlias = new HashMap(); + if ((widgetData.getString("type").equalsIgnoreCase("table") || widgetData.getString("type").equalsIgnoreCase("advanced-table")) && widgetContent.has("columnSelectedOfDataset")) { for (int i = 0; i < widgetContent.getJSONArray("columnSelectedOfDataset").length(); i++) { @@ -635,18 +639,25 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam JSONObject columnOld = columns.getJSONObject(j); if (column.has("name")) { if (columnOld.getString("header").equals(column.getString("name"))) { - + headerToAlias.put(columnOld.getString("header"), column.getString("name")); columnsOrdered.put(columnOld); break; } else if (columnOld.getString("header").equals(column.getString("aliasToShow"))) { + headerToAlias.put(columnOld.getString("header"), column.getString("name")); + columnsOrdered.put(columnOld); + break; + } else if (columnOld.getString("header").equals(mapColumnsAggregations.get(column.getString("aliasToShow")))) { + headerToAlias.put(columnOld.getString("header"), column.getString("name")); columnsOrdered.put(columnOld); break; } } else { if (columnOld.getString("header").equals(column.getString("alias"))) { + headerToAlias.put(columnOld.getString("header"), column.getString("alias")); columnsOrdered.put(columnOld); break; } else if (columnOld.getString("header").equals(column.getString("aliasToShow"))) { + headerToAlias.put(columnOld.getString("header"), column.getString("aliasToShow")); columnsOrdered.put(columnOld); break; } @@ -657,6 +668,65 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam } else { columnsOrdered = columns; } + int isGroup = 0; + if (widgetContent.has("columnSelectedOfDataset")) + mapGroupsAndColumns = getMapFromGroupsArray(groupsArray, widgetContent.getJSONArray("columnSelectedOfDataset")); + + Row header = null; + Row newheader = null; + if (exportWidget) { + widgetName = WorkbookUtil.createSafeSheetName(widgetName); + sheet = wb.createSheet(widgetName); + + // Create HEADER - Column Names + if (!mapGroupsAndColumns.isEmpty()) { + isGroup = 1; + newheader = sheet.createRow((short) 0); + for (int i = 0; i < columnsOrdered.length(); i++) { + JSONObject column = columnsOrdered.getJSONObject(i); + String groupName = mapGroupsAndColumns.get(headerToAlias.get(column.get("header"))); + if (groupName != null) { + Cell cell = newheader.createCell(i); + cell.setCellValue(groupName); + } + + } + header = sheet.createRow((short) 1); + } else + header = sheet.createRow((short) 0); // first row + } else { + String sheetName = "empty"; + if (dataStore.has("widgetName") && dataStore.getString("widgetName") != null && !dataStore.getString("widgetName").isEmpty()) { + if (dataStore.has("sheetInfo")) { + sheetName = dataStore.getString("sheetInfo").concat(".").concat(widgetName); + } else { + sheetName = widgetName; + } + } + + sheetName = WorkbookUtil.createSafeSheetName(sheetName); + sheet = wb.createSheet(sheetName); + // First row for Widget name in case exporting whole Cockpit document + Row firstRow = sheet.createRow((short) 0); + Cell firstCell = firstRow.createCell(0); + firstCell.setCellValue(widgetName); + // Create HEADER - Column Names + if (!mapGroupsAndColumns.isEmpty()) { + isGroup = 1; + newheader = sheet.createRow((short) 1); + for (int i = 0; i < columnsOrdered.length(); i++) { + JSONObject column = columnsOrdered.getJSONObject(i); + String groupName = mapGroupsAndColumns.get(headerToAlias.get(column.get("header"))); + if (groupName != null) { + Cell cell = newheader.createCell(i); + cell.setCellValue(groupName); + } + + } + header = sheet.createRow((short) 2); + } else + header = sheet.createRow((short) 1); + } for (int i = 0; i < columnsOrdered.length(); i++) { JSONObject column = columnsOrdered.getJSONObject(i); @@ -684,9 +754,9 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam JSONObject rowObject = rows.getJSONObject(r); Row row; if (exportWidget) - row = sheet.createRow(r + 1); // starting from second row, because the 0th (first) is Header + row = sheet.createRow((r + isGroup) + 1); // starting from second row, because the 0th (first) is Header else - row = sheet.createRow(r + 2); + row = sheet.createRow((r + isGroup) + 2); for (int c = 0; c < columnsOrdered.length(); c++) { JSONObject column = columnsOrdered.getJSONObject(c); @@ -727,6 +797,76 @@ private void createExcelFile(JSONObject dataStore, Workbook wb, String widgetNam } } + private HashMap getMapFromGroupsArray(JSONArray groupsArray, JSONArray aggr) throws JSONException { + HashMap returnMap = new HashMap(); + if (aggr != null && groupsArray != null) { + + for (int i = 0; i < groupsArray.length(); i++) { + + String id = groupsArray.getJSONObject(i).getString("id"); + String groupName = groupsArray.getJSONObject(i).getString("name"); + + for (int ii = 0; ii < aggr.length(); ii++) { + JSONObject column = aggr.getJSONObject(ii); + + if (column.has("group") && column.getString("group").equals(id)) { + String nameToInsert = ""; + if (!column.has("name")) + nameToInsert = column.getString("alias"); + else + nameToInsert = column.getString("name"); + + returnMap.put(nameToInsert, groupName); + } + + } + } + } + + return returnMap; + + } + + private HashMap getMapFromAggregationsFromArray(JSONArray aggr) throws JSONException { + HashMap returnMap = new HashMap(); + if (aggr != null) { + for (int i = 0; i < aggr.length(); i++) { + JSONObject column = aggr.getJSONObject(i); + String nameToInsert = ""; + if (!column.has("name")) + nameToInsert = column.getString("alias"); + else + nameToInsert = column.getString("name"); + returnMap.put(nameToInsert, column.getString("aliasToShow")); + + } + + } + + return returnMap; + + } + + private HashMap getMapFromAggregations(JSONObject aggr) throws JSONException { + + HashMap returnMap = new HashMap(); + if (aggr.has("measures")) { + JSONArray measures = aggr.getJSONArray("measures"); + + for (int i = 0; i < measures.length(); i++) { + returnMap.put(measures.getJSONObject(i).getString("id"), measures.getJSONObject(i).getString("alias")); + } + } + if (aggr.has("categories")) { + JSONArray categories = aggr.getJSONArray("categories"); + + for (int i = 0; i < categories.length(); i++) { + returnMap.put(categories.getJSONObject(i).getString("id"), categories.getJSONObject(i).getString("alias")); + } + } + return returnMap; + } + private JSONArray filterDataStoreColumns(JSONArray columns) { try { for (int i = 0; i < columns.length(); i++) { @@ -914,6 +1054,7 @@ private List getDatastoresByWidget(JSONObject template) throws JSONE if (body != null) { logger.debug("Export cockpit body.toString(): " + body.toString()); } + JSONObject datastoreObj = getDatastore(datasetLabel, map, body.toString()); if (datastoreObj != null) { @@ -963,7 +1104,6 @@ private void exportWidgetsToExcel(List excelSheets, Workbook wb) thr } private void loadCockpitSelections(JSONObject configuration) throws JSONException { - // String[] cockpitSelections = parameterMap.get("COCKPIT_SELECTIONS"); JSONObject cockpitSelections = body.optJSONObject("COCKPIT_SELECTIONS"); if (cockpitSelections != null) { JSONArray configDatasets = configuration.getJSONArray("datasets"); @@ -1042,14 +1182,38 @@ private void loadAggregationsFromCockpitSelections(JSONObject paramDatasets, JSO String keyToAdd = keys.next(); if (jsonobject.getString("urlName").equals(keyToAdd)) { - jsnParam.put(jsonobject.getString("urlName"), jsonobject.getString("parameterValue")); + jsnParam.put(jsonobject.getString("urlName"), valuesToChange); } else { - jsnParam.put(datasetVals.getString(keyToAdd), ""); + if (datasetVals.getString(keyToAdd) != null && !datasetVals.getString(keyToAdd).isEmpty()) { + jsnParam.put(keyToAdd, ""); + } } } - newParameters.put(obj, jsnParam); + if (newParameters.has(obj)) { + JSONObject jsonobjectVals = newParameters.getJSONObject(obj); + + if (jsonobjectVals != null) { + Iterator keysJ = jsonobjectVals.keys(); + while (keysJ.hasNext()) { + String keyToAdd = keysJ.next(); + String newKeyToAdd = keyToAdd.replace("$P{", "").replace("}", ""); + if (jsonobjectVals.has(newKeyToAdd) && !jsonobjectVals.getString(newKeyToAdd).isEmpty() + && jsnParam.getString(datasetVals.getString(keyToAdd)).isEmpty()) { + if (jsnParam.has(datasetVals.getString(keyToAdd))) + jsnParam.remove(datasetVals.getString(keyToAdd)); + + jsnParam.put(newKeyToAdd, jsonobjectVals.getString(newKeyToAdd)); + } + } + + newParameters.put(obj, jsnParam); + } + + } else { + newParameters.put(obj, jsnParam); + } } } else { newParameters.put(obj, valuesToChange); @@ -1078,7 +1242,10 @@ private void loadAggregationsFromCockpitSelections(JSONObject paramDatasets, JSO } } else if ((val != null && val.length() > 0) && (!val.contains("$P{"))) { // parameter already set in data configuration - newParameters.put(obj, val); + if (paramDatasets.has(obj)) + newParameters.put(obj, paramDatasets.getJSONObject(obj)); + else + newParameters.put(obj, val); } } @@ -1105,6 +1272,20 @@ private void loadAggregationsFromCockpitSelections(JSONObject paramDatasets, JSO found = true; nearRealArray.put(paramss[j]); } + JSONObject paramDataset = paramDatasets.getJSONObject(stringToCheck); + JSONObject newParametersData = newParameters.getJSONObject(stringToCheck); + Iterator keys = paramDataset.keys(); + + while (keys.hasNext()) { + String key = (String) keys.next(); + + if (!newParametersData.has(key)) { + newParametersData.put(key, paramDataset.get(key)); + } + + } + newParameters.remove(stringToCheck); + newParameters.put(stringToCheck, newParametersData); } if (!found) { newParameters.remove(paramss[j]); @@ -1112,17 +1293,43 @@ private void loadAggregationsFromCockpitSelections(JSONObject paramDatasets, JSO } + // logger.debug("associativeSelectionsPayload newParameters: [" + newParameters.toString() + "]"); associativeSelectionsPayload.put("datasets", newParameters); associativeSelectionsPayload.put("nearRealtime", nearRealArray); AssociativeSelectionsClient client = new AssociativeSelectionsClient(); try { + logger.debug("associativeSelectionsPayload: [" + associativeSelectionsPayload.toString() + "]"); JSONObject associativeSelections = client.getAssociativeSelections(new HashMap(), userUniqueIdentifier, associativeSelectionsPayload.toString()); + // I have to update parameters with ASSOCIATIONS PARAMETERS that could have different names (!!!) + + if (associativeSelectionsPayload.has("associationGroup")) { + JSONObject associationGroup = associativeSelectionsPayload.getJSONObject("associationGroup"); + if (associationGroup.has("associations") && associationGroup.getJSONArray("associations").length() != 0) { + JSONArray associationGroupArray = associationGroup.getJSONArray("associations"); + for (int j = 0; j < associationGroupArray.length(); j++) { + + JSONObject association = associationGroupArray.getJSONObject(j); + JSONArray fields = association.getJSONArray("fields"); + String dataValue = ""; + String dataAssValue = ""; + for (int k = 0; k < fields.length(); k++) { + if (fields.getJSONObject(k).getString("column").contains("$P")) { + dataValue = fields.getJSONObject(k).getString("column").replace("$P{", "").replace("}", ""); + } else { + dataAssValue = fields.getJSONObject(k).getString("column"); + } + } + associativeToDatasetParametersMap.put(dataAssValue, dataValue); + + } + } + } JSONArray datasetLabels = aggregation.getJSONArray("datasets"); - for (int j = 0; j < datasetLabels.length(); j++) { - String label = datasetLabels.getString(j); + for (int j3 = 0; j3 < datasetLabels.length(); j3++) { + String label = datasetLabels.getString(j3); actualSelectionMap.put(label, associativeSelections.getJSONObject(label)); } } catch (Exception e) { @@ -1188,6 +1395,21 @@ private JSONObject getDatastore(String datasetLabel, Map map, St private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject configuration, String widgetType) throws JSONException { JSONObject aggregations = new JSONObject(); + JSONArray widgetsMapAggregations = new JSONArray(); + if (body.has("widgetsMapAggregations")) + widgetsMapAggregations = body.getJSONArray("widgetsMapAggregations"); + JSONObject content = widget.optJSONObject("content"); + JSONArray aggrNewVar = new JSONArray(); + HashMap mapColumnsAggregations = new HashMap(); + if (widgetsMapAggregations != null && !widgetsMapAggregations.isNull(0)) { + + if (widgetsMapAggregations.getJSONObject(0).has("columnSelectedOfDataset")) + aggrNewVar = (JSONArray) widgetsMapAggregations.getJSONObject(0).get("columnSelectedOfDataset"); + + if (widget.has("id") && widget.getInt("id") == widgetsMapAggregations.getJSONObject(0).getInt("id")) + mapColumnsAggregations = getMapFromAggregationsFromArray(aggrNewVar); + + } JSONArray measures = new JSONArray(); aggregations.put("measures", measures); @@ -1197,7 +1419,12 @@ private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject confi String sortingColumn = null; String sortingOrder = null; - JSONObject settings = widget.optJSONObject("content"); + JSONObject contents = widget.optJSONObject("content"); + if (contents != null) { + sortingColumn = contents.optString("sortingColumn"); + sortingOrder = contents.optString("sortingOrder"); + } + JSONObject settings = widget.optJSONObject("settings"); if (settings != null) { sortingColumn = settings.optString("sortingColumn"); sortingOrder = settings.optString("sortingOrder"); @@ -1211,7 +1438,7 @@ private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject confi boolean isSortingUsed = false; boolean isSolrDataset = isSolrDataset(dataset); - JSONObject content = widget.optJSONObject("content"); + if (content != null) { widgetType = widget.getString("type"); @@ -1263,6 +1490,11 @@ private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject confi String aliasToShow = column.optString("aliasToShow"); if (aliasToShow != null && aliasToShow.isEmpty()) { aliasToShow = column.getString("alias"); + + } + + if (!mapColumnsAggregations.isEmpty()) { + aliasToShow = mapColumnsAggregations.get(column.getString("name")); } JSONObject categoryOrMeasure = new JSONObject(); @@ -1271,9 +1503,13 @@ private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject confi String formula = column.optString("formula"); String name = formula.isEmpty() ? column.optString("name") : formula; + if (column.has("formula")) { + categoryOrMeasure.put("formula", formula); + } categoryOrMeasure.put("columnName", name); if (isSortingDefined && column.has("name") && sortingColumn.equals(name)) { categoryOrMeasure.put("orderType", sortingOrder); + categoryOrMeasure.put("orderColumn", sortingColumn); isSortingUsed = true; } else { categoryOrMeasure.put("orderType", ""); @@ -1317,12 +1553,15 @@ private JSONObject getAggregationsFromWidget(JSONObject widget, JSONObject confi private JSONObject getParametersFromWidget(JSONObject widget, JSONObject configuration) throws JSONException { JSONArray cockpitSelectionsDatasetParameters = null; + JSONArray associationsJSON = new JSONArray(); + if (configuration.has("associations")) { + associationsJSON = configuration.getJSONArray("associations"); + } try { cockpitSelectionsDatasetParameters = body.getJSONArray("parametersDataArray"); } catch (JSONException e) { logger.warn("No cockpit selections specified"); } - JSONObject dataset = getDatasetFromWidget(widget, configuration); JSONObject parameters = dataset.getJSONObject("parameters"); String datasetName = dataset.getString("name"); @@ -1339,10 +1578,34 @@ private JSONObject getParametersFromWidget(JSONObject widget, JSONObject configu String key = actualSelectionKeys.next(); if (key.contains("$")) { Object values = actualSelections.get(key); + if (values != null && !String.valueOf(values).isEmpty()) { + String cleanPar = key.replace("$P{", ""); + cleanPar = cleanPar.replace("}", ""); + if (newParameters.has(cleanPar)) { + newParameters.remove(cleanPar); + } + } newParameters.put(key, values); } + } - JSONObject params = getReplacedAssociativeParameters(parameters, newParameters); + + for (String keys : actualSelectionMap.keySet()) { + if (!keys.equals(datasetName)) { + JSONObject actualSelectionsOther = actualSelectionMap.get(keys); + Iterator actualSelectionKeys2 = actualSelectionsOther.keys(); + while (actualSelectionKeys2.hasNext()) { + String key = actualSelectionKeys2.next(); + if (parameters.has(associativeToDatasetParametersMap.get(key)) && newParameters.has(associativeToDatasetParametersMap.get(key)) + && !actualSelectionsOther.getString(key).isEmpty()) { + newParameters.put("$P{" + associativeToDatasetParametersMap.get(key) + "}", actualSelectionsOther.get(key)); + + } + } + } + } + + JSONObject params = getReplacedAssociativeParameters(parameters, newParameters, associationsJSON); newParameters = getReplacedParameters(params, datasetId); } if (cockpitSelectionsDatasetParameters != null && cockpitSelectionsDatasetParameters.length() > 0 && parameters.length() != 0) { @@ -1372,8 +1635,12 @@ private JSONObject getParametersFromWidget(JSONObject widget, JSONObject configu valuesToChange = valuesToChange.replaceAll("\\[", "").replaceAll("\\]", ""); valuesToChange = valuesToChange.replaceAll("\"", ""); // single value parameter } - if (!(newParameters.length() != 0 && newParameters.has(key) && newParameters.getString(key).length() != 0)) - newParameters.put(obj, valuesToChange); + if (!(newParameters.length() != 0 && newParameters.has(key) && newParameters.getString(key).length() != 0)) { + if (!(associationsJSON.toString().contains(obj) && newParameters.has(obj) && !newParameters.getString(obj).isEmpty() + && !newParameters.getString(obj).contains("$P"))) + newParameters.put(obj, valuesToChange); + } + } else { if (!(newParameters.has(obj) && !newParameters.getString(obj).isEmpty())) @@ -1387,7 +1654,10 @@ private JSONObject getParametersFromWidget(JSONObject widget, JSONObject configu } } - + for (int i = 0; i < parameters.length(); i++) { + if (!newParameters.has(parameters.names().getString(i))) + newParameters.put(parameters.names().getString(i), ""); + } return newParameters; } else return getReplacedParameters(parameters, datasetId); @@ -1400,7 +1670,7 @@ private boolean isSolrDataset(IDataSet dataSet) { return dataSet instanceof SolrDataSet; } - private JSONObject getReplacedAssociativeParameters(JSONObject oldParameters, JSONObject newParameters) throws JSONException { + private JSONObject getReplacedAssociativeParameters(JSONObject oldParameters, JSONObject newParameters, JSONArray associationsJSON) throws JSONException { JSONObject parameters = new JSONObject(); Iterator newParameterKeys = newParameters.keys(); while (newParameterKeys.hasNext()) { @@ -1409,17 +1679,65 @@ private JSONObject getReplacedAssociativeParameters(JSONObject oldParameters, JS Matcher parameterMatcher = Pattern.compile(regex).matcher(parameter); if (parameterMatcher.matches()) { String parameterName = parameterMatcher.group(1); - Object exists = oldParameters.get(parameterName); - if (exists != null) { + if (oldParameters.has(parameterName)) { + // JSONArray value = (JSONArray) newParameters.get(parameter); + // String regex2 = "\\((?:(?:,)?(?:\\'([a-zA-Z0-9\\-\\_\\s]+)\\')(?:,+)?)+\\)"; + // String valueToElaborate = value.get(0).toString(); + // Matcher parameterMatcher2 = Pattern.compile(regex2).matcher(valueToElaborate); + // String realValueToAdd = ""; + // String realValue = ""; + // while (parameterMatcher2.find()) { + // if (realValue.isEmpty()) + // realValueToAdd = parameterMatcher2.group(1); + // else + // realValueToAdd = realValueToAdd + "," + parameterMatcher2.group(1); + // + // realValue = parameterMatcher2.group(1); + // valueToElaborate = valueToElaborate.replace("'" + realValue + "'", ""); + // parameterMatcher2 = Pattern.compile(regex2).matcher(valueToElaborate); + // } + // parameters.put(parameterName, realValueToAdd); JSONArray value = (JSONArray) newParameters.get(parameter); String regex2 = "\\(\\'(.*)\\'\\)"; - Matcher parameterMatcher2 = Pattern.compile(regex2).matcher(value.get(0).toString()); - if (parameterMatcher2.matches()) { - String realValue = parameterMatcher2.group(1); - parameters.put(parameterName, realValue); + String[] valueToPut = new String[value.length()]; + for (int i = 0; i < value.length(); i++) { + + Matcher parameterMatcher2 = Pattern.compile(regex2).matcher(value.get(i).toString()); + if (parameterMatcher2.matches()) { + String realValue = parameterMatcher2.group(1); + if (realValue.contains("','")) { + realValue = realValue.replaceAll("','", ","); + } + if (oldParameters.getString(parameterName).isEmpty() && associationsJSON.toString().contains(parameterName)) { + valueToPut[i] = realValue; + } else if (!oldParameters.getString(parameterName).isEmpty() && associationsJSON.toString().contains(parameterName)) { + valueToPut[i] = realValue; + } else { + realValue = "'" + realValue + "'"; + valueToPut[i] = realValue; + } + } + } + String parToPut = StringUtils.join(valueToPut, ","); + parameters.put(parameterName, parToPut); } } +// else if (associationsJSON.toString().contains(parameter) && newParameters.has(parameter)) { +// +// Object obj = newParameters.get("$P{" + parameter + "}"); +// if (obj instanceof JSONArray && newParameters.getString(parameter).isEmpty()) { +// +// JSONArray value = (JSONArray) newParameters.get(parameter); +// String regex2 = "\\(\\'(.*)\\'\\)"; +// Matcher parameterMatcher2 = Pattern.compile(regex2).matcher(value.get(0).toString()); +// if (parameterMatcher2.matches()) { +// String realValue = parameterMatcher2.group(1); +// parameters.put(parameter, realValue); +// } +// } +// } + } return parameters; } @@ -1508,22 +1826,14 @@ private JSONArray getSummaryRowFromWidget(JSONObject widget) throws JSONExceptio JSONObject measure = new JSONObject(); measure.put("id", column.getString("alias")); measure.put("alias", column.getString("aliasToShow")); - if (column.has("datasetOrTableFlag")) { - // calculated field case - measure.put("datasetOrTableFlag", column.getBoolean("datasetOrTableFlag")); - } - if (column.has("datasetOrTableFlag") && !column.getBoolean("datasetOrTableFlag")) { - // in case of table-level calculaated field and the measures have no aggregation set, on summary row it must - // be - // changed to - // be SUM instead - String formula = getSummaryRowFormula(column); - measure.put("columnName", formula); - } else { - String formula = column.optString("formula"); - String name = formula.isEmpty() ? column.optString("name") : formula; + + String formula = column.optString("formula"); + String name = formula.isEmpty() ? column.optString("name") : formula; + if (column.has("formula")) { + measure.put("formula", name); + } else measure.put("columnName", name); - } + measure.put("funct", column.getString("funcSummary")); boolean hidden = false; @@ -1572,22 +1882,14 @@ private JSONArray getSummaryRowFromWidget(JSONObject widget) throws JSONExceptio JSONObject measure = new JSONObject(); measure.put("id", column.getString("alias")); measure.put("alias", column.getString("aliasToShow")); - if (column.has("datasetOrTableFlag")) { - // calculated field case - measure.put("datasetOrTableFlag", column.getBoolean("datasetOrTableFlag")); - } - if (column.has("datasetOrTableFlag") && !column.getBoolean("datasetOrTableFlag")) { - // in case of table-level calculaated field and the measures have no aggregation set, on summary row it must - // be - // changed to - // be SUM instead - String formula = getSummaryRowFormula(column); - measure.put("columnName", formula); - } else { - String formula = column.optString("formula"); - String name = formula.isEmpty() ? column.optString("name") : formula; + + String formula = column.optString("formula"); + String name = formula.isEmpty() ? column.optString("name") : formula; + if (column.has("formula")) { + measure.put("formula", name); + } else measure.put("columnName", name); - } + measure.put("funct", aggrObj.get("aggregation")); boolean hidden = false; @@ -1638,22 +1940,14 @@ private JSONArray getSummaryRowFromWidget(JSONObject widget) throws JSONExceptio JSONObject measure = new JSONObject(); measure.put("id", column.getString("alias")); measure.put("alias", column.getString("aliasToShow")); - if (column.has("datasetOrTableFlag")) { - // calculated field case - measure.put("datasetOrTableFlag", column.getBoolean("datasetOrTableFlag")); - } - if (column.has("datasetOrTableFlag") && !column.getBoolean("datasetOrTableFlag")) { - // in case of table-level calculaated field and the measures have no aggregation set, on summary row it must be - // changed - // to - // be SUM instead - String formula = getSummaryRowFormula(column); - measure.put("columnName", formula); - } else { - String formula = column.optString("formula"); - String name = formula.isEmpty() ? column.optString("name") : formula; + + String formula = column.optString("formula"); + String name = formula.isEmpty() ? column.optString("name") : formula; + if (column.has("formula")) { + measure.put("formula", name); + } else measure.put("columnName", name); - } + measure.put("funct", column.getString("funcSummary")); boolean hidden = false; @@ -1785,6 +2079,7 @@ private JSONObject getLikeSelectionsFromWidget(JSONObject widget, JSONObject con private JSONObject getSelectionsFromWidget(JSONObject widget, JSONObject configuration) throws JSONException { JSONObject dataset = getDatasetFromWidget(widget, configuration); String datasetName = dataset.getString("name"); + String datasetLabel = dataset.getString("dsLabel"); JSONObject selections = new JSONObject(); JSONObject datasetFilters = new JSONObject(); @@ -1854,6 +2149,7 @@ private JSONObject getSelectionsFromWidget(JSONObject widget, JSONObject configu } } + boolean useLabel = false; if (actualSelectionMap.containsKey(datasetName)) { JSONObject actualSelections = actualSelectionMap.get(datasetName); Iterator actualSelectionKeys = actualSelections.keys(); @@ -1864,9 +2160,24 @@ private JSONObject getSelectionsFromWidget(JSONObject widget, JSONObject configu datasetFilters.put(key, values); } } + } else if (actualSelectionMap.containsKey(datasetLabel)) { + useLabel = true; + JSONObject actualSelections = actualSelectionMap.get(datasetLabel); + Iterator actualSelectionKeys = actualSelections.keys(); + while (actualSelectionKeys.hasNext()) { + String key = actualSelectionKeys.next(); + if (!key.contains("$")) { + Object values = actualSelections.get(key); + datasetFilters.put(key, values); + } + } } - selections.put(datasetName, datasetFilters); + if (useLabel) { + selections.put(datasetLabel, datasetFilters); + } else { + selections.put(datasetName, datasetFilters); + } return selections; } diff --git a/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..f9f332b160b --- /dev/null +++ b/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,99 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.apache.log4j.LogMF; +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.cache.CacheInterface; +import it.eng.spagobi.utilities.cache.ConfigurationCache; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + private static final String CONFIGURATION_MAP = "CONFIGURATION_MAP"; + + private final Lock lock = new ReentrantLock(); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + CacheInterface cache = ConfigurationCache.getCache(); + HashMap configurations = (HashMap) cache.get(CONFIGURATION_MAP); + if (configurations == null) { + lock.lock(); + try { + configurations = (HashMap) cache.get(CONFIGURATION_MAP); + if (configurations == null) { + HashMap newConfiguration = loadConfigurations(); + cache.put(CONFIGURATION_MAP, newConfiguration); + configurations = newConfiguration; + } + } finally { + lock.unlock(); + } + } + String toReturn = configurations.get(key); + LogMF.debug(logger, "GET : [{0}] = [{01]", key, toReturn); + return toReturn; + } + + private HashMap loadConfigurations() { + logger.debug("IN"); + IConfigDAO dao = null; + HashMap configurations = null; + try { + configurations = new HashMap(); + dao = DAOFactory.getSbiConfigDAO(); + List allConfig = dao.loadAllConfigParameters(); + if (allConfig.isEmpty()) { + logger.error("The table sbi_config is EMPTY"); + } + for (Config config : allConfig) { + configurations.put(config.getLabel(), config.getValueCheck() != null ? config.getValueCheck() : ""); + logger.info("Retrieved configuration: " + config.getLabel() + " / " + config.getValueCheck()); + } + } catch (Exception e) { + logger.error("Impossible to get configuration", e); + throw new SpagoBIRuntimeException("Impossible to get configuration", e); + } finally { + logger.debug("OUT"); + } + return configurations; + } + +} diff --git a/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 5baa9837fc0..00000000000 --- a/knowagecockpitengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagecockpitengine/src/main/java/it/eng/spagobi/engine/chart/util/DataSetTransformer.java b/knowagecockpitengine/src/main/java/it/eng/spagobi/engine/chart/util/DataSetTransformer.java index b8fa4b0f0c0..6dfc289e7c7 100644 --- a/knowagecockpitengine/src/main/java/it/eng/spagobi/engine/chart/util/DataSetTransformer.java +++ b/knowagecockpitengine/src/main/java/it/eng/spagobi/engine/chart/util/DataSetTransformer.java @@ -852,8 +852,8 @@ private void removeOrderColumn(Map dataColumnsMapper, Map keyMapper = (Map) drillOrder.get(key); - if (!keyMapper.get("orderColumn").equals("") && !keyMapper.get("orderColumn").equals(categorieColumns.get("column")) - && !drillOrder.containsKey(keyMapper.get("orderColumn"))) { + if (keyMapper.get("orderColumn") != null && !keyMapper.get("orderColumn").equals("") + && !keyMapper.get("orderColumn").equals(categorieColumns.get("column")) && !drillOrder.containsKey(keyMapper.get("orderColumn"))) { dataColumnsMapper.remove(keyMapper.get("orderColumn").toLowerCase()); } } @@ -1334,15 +1334,15 @@ public Map getData(List dataRows, Object serie, Object columnsNeeded, Ob for (int i = 0; i < dataRows.size(); i++) { Map row = (Map) dataRows.get(i); - HashMap record = new HashMap<>(); + HashMap record = new HashMap<>(); /* For every record take these columns */ for (int j = 0; j < listColumns.size(); j++) { Object x = row.get(listColumns.get(j)); - record.put(columns.get(j).toString(), x.toString()); + record.put(columns.get(j).toString(), x); } - record.put(serie.toString(), row.get(serieRawColumn).toString()); + record.put(serie.toString(), row.get(serieRawColumn)); firstresult.put(new Integer(i), record); } @@ -1437,7 +1437,7 @@ public JSONArray getStoreResult(Map firstresult, Object column JSONArray storeResult = new JSONArray(); - HashMap storeResultMap = new HashMap<>(); + HashMap storeResultMap = new HashMap<>(); int value = 0; @@ -1445,7 +1445,7 @@ public JSONArray getStoreResult(Map firstresult, Object column if (!storeResultMap.containsValue(firstresult.get(i).get(column.toString()))) { - storeResultMap.put(value, (String) (firstresult.get(i).get(column.toString()))); + storeResultMap.put(value, (firstresult.get(i).get(column.toString()))); value++; @@ -1472,7 +1472,7 @@ public JSONArray getResult(Map firstresult, Object serie, Hash JSONObject jo = new JSONObject(); - Double serieValue = Double.valueOf((String) firstresult.get(i).get(serie.toString())); + Double serieValue = Double.valueOf(firstresult.get(i).get(serie).toString()); jo.put(serie.toString(), serieValue); diff --git a/knowagecockpitengine/src/main/resources/chart/templates/d3js244/parallel_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/d3js244/parallel_chart.vm index e3b2d7985e1..d7f8fa0c563 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/d3js244/parallel_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/d3js244/parallel_chart.vm @@ -344,7 +344,12 @@ ##maxHeight: '$chart.PARALLEL_TOOLTIP.style.maxHeight', ##padding: '$chart.PARALLEL_TOOLTIP.style.padding', border: '$chart.PARALLEL_TOOLTIP.style.border', - borderRadius: '$chart.PARALLEL_TOOLTIP.style.borderRadius' + borderRadius: '$chart.PARALLEL_TOOLTIP.style.borderRadius', + #if($chart.PARALLEL_TOOLTIP.maxNumberOfRecords) + maxNumberOfRecords: $chart.PARALLEL_TOOLTIP.maxNumberOfRecords + #else + maxNumberOfRecords: 50 + #end }, emptymessage: diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/bubble_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/bubble_chart.vm index c21aef9c22b..3c9bf0b2f2c 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/bubble_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/bubble_chart.vm @@ -598,12 +598,12 @@ #if($xAxis.plotBands.get(0).from=="") from :0, #else - from : $xAxis.plotBands.get(0).from, + from : '$xAxis.plotBands.get(0).from', #end #if($xAxis.plotBands.get(0).to=="") to :0, #else - to : $xAxis.plotBands.get(0).to, + to : '$xAxis.plotBands.get(0).to', #end }, ], @@ -679,7 +679,59 @@ step: $xAxis.step, #end #end - + formatter: function () { + var value = this.value; + var newValue = ""; + var scaleFactor = $isCockpit ? '${xAxis.labels.scaleFactor}' : '${xAxis.LABELS.scaleFactor}' + if(scaleFactor.indexOf("xAxis")!=-1){ + scaleFactor = "empty" + } + var prefixValue = ''; + var sufixValue = ''; + + + var decimalPoints = Highcharts.getOptions().lang.decimalPoint; + var thousandsSep = Highcharts.getOptions().lang.thousandsSep; + + var precision = $isCockpit ? '${xAxis.labels.precision}' : '${xAxis.LABELS.precision}' + if(precision.indexOf("xAxis")!=-1){ + precision = 0 + } + + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + /* No selection is provided for the number to be displayed as the data label (pure value). */ + newValue = Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + case "K": + newValue = Highcharts.numberFormat(value/Math.pow(10,3),precision,decimalPoints,thousandsSep) + "k"; + break; + case "M": + newValue = Highcharts.numberFormat(value/Math.pow(10,6),precision,decimalPoints,thousandsSep) + "M"; + break; + case "G": + newValue = Highcharts.numberFormat(value/Math.pow(10,9),precision,decimalPoints,thousandsSep) + "G"; + break; + case "T": + newValue = Highcharts.numberFormat(value/Math.pow(10,12),precision,decimalPoints,thousandsSep) + "T"; + break; + case "P": + newValue = Highcharts.numberFormat(value/Math.pow(10,15),precision,decimalPoints,thousandsSep) + "P"; + break; + case "E": + newValue = Highcharts.numberFormat(value/Math.pow(10,18),precision,decimalPoints,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + newValue = Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + + } + + return newValue ; + } , #if( $xAxis.style != '' ) style:{ #foreach($styleName in $xAxis.style.keySet()) @@ -726,7 +778,77 @@ #end }, - + + + #if($xAxis.MAJORGRID) + #if($xAxis.MAJORGRID.interval != '') + tickInterval: $xAxis.MAJORGRID.interval, + gridLineWidth: 1, + #end + + #if($xAxis.MAJORGRID.style.color != '') + gridLineColor: '$xAxis.MAJORGRID.style.color', + #end + + #set($typeline = $xAxis.MAJORGRID.style.typeline) + #if($xAxis.MAJORGRID.style.typeline != '') + #if($typeline == 'dashed') + #set($convertedTypeline = 'Dash') + #elseif($typeline == 'dotted') + #set($convertedTypeline = 'Dot') + #elseif($typeline == 'solid') + #set($convertedTypeline = 'Solid') + #else + #set($convertedTypeline = $typeline) + #end + gridLineDashStyle: '$convertedTypeline', + #end + #end + + + #if($xAxis.MINORGRID) + #if($xAxis.MINORGRID.interval != '') + minorTickInterval: $xAxis.MINORGRID.interval, + #end + + #if($xAxis.MINORGRID.style.color != '') + minorGridLineColor: '$xAxis.MINORGRID.style.color', + #end + + #set($typeline = $xAxis.MINORGRID.style.typeline) + #if($typeline == 'dashed') + #set($convertedMinorTpeline = 'Dash') + #elseif($typeline == 'dotted') + #set($convertedMinorTpeline = 'Dot') + #elseif($typeline == 'solid') + #set($convertedMinorTpeline = 'Solid') + #end + minorGridLineDashStyle: '$convertedMinorTpeline', + #end + + + + #set($Integer1 = 0) + #if($xAxis.min==$xAxis.max) + #set ($minAndMaxAreSame= true) + #end + #if($xAxis.min && $xAxis.min != "auto" && $xAxis.min!='') + #set ($min = $xAxis.min) + min: $xAxis.min, + #end + #if($xAxis.max && $xAxis.max!='auto' && $xAxis.max!='') + #set ($max = $xAxis.max) + #if($min) + #if($Integer1.parseInt($min)<$Integer1.parseInt($max)) + max:$xAxis.max, + #end + #else + max:$xAxis.max, + #end + + #end + + #if($xAxis.position == 'top') opposite: true, #end @@ -764,12 +886,12 @@ #if($yAxis.plotBands.get(0).from=="") from :0, #else - from : $yAxis.plotBands.get(0).from, + from : '$yAxis.plotBands.get(0).from', #end #if($yAxis.plotBands.get(0).to=="") to :0, #else - to : $yAxis.plotBands.get(0).to, + to : '$yAxis.plotBands.get(0).to', #end }, ], @@ -801,24 +923,31 @@ #if($yAxis.min==$yAxis.max) #set ($minAndMaxAreSame= true) #end - #if($yAxis.min && $yAxis.min != "auto" && $yAxis.min!='' ) - #set ($min = $yAxis.min) - min: $yAxis.min, - startOnTick:false, + #if($yAxis.min) + #if($yAxis.min != "auto" && $yAxis.min!='') + #set ($min = $yAxis.min) + min: $yAxis.min, + startOnTick:false, + #elseif($yAxis.min == "auto" || $yAxis.min=='') + min: "$yAxis.min", + #end #end - - #if($yAxis.max && $yAxis.max!='auto' && $yAxis.max!='' ) - #set ($max = $yAxis.max) - #if($min) - #if($Integer1.parseInt($min)<$Integer1.parseInt($max)) + #if($yAxis.max) + #if($yAxis.max!='auto' && $yAxis.max!='') + #set ($max = $yAxis.max) + #if($min) + #if($Integer1.parseInt($min)<$Integer1.parseInt($max)) + max:$yAxis.max, + endOnTick: false, + #end + #else max:$yAxis.max, endOnTick: false, #end - #else - max:$yAxis.max, - endOnTick: false, + #elseif(($yAxis.max == "auto" || $yAxis.max=='') && $chartType != "radar") + max: "$yAxis.max", #end - #end + #end @@ -1058,7 +1187,7 @@ name: "$escapeTool.javascript($relatedSerie.name)", #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($relatedSerie.name)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($relatedSerie.name)) color:'$customColor.customValue', #end #end @@ -1097,7 +1226,7 @@ name: "$serieCategoryName", #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($serieCategoryName)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($serieCategoryName)) color:'$customColor.customValue', #end #end @@ -1301,8 +1430,8 @@ yAxis: $yAxisPositions[$referencedAxis], #end #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($escapeTool.javascript($valueKey))) - color:'$customColor.customValue', + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($escapeTool.javascript($valueKey))) + color:'$customColor.customValue', #end #end @@ -1325,7 +1454,7 @@ name: "$escapeTool.javascript($el.name)", #end #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($el.name)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($el.name)) color:'$customColor.customValue', #end #end @@ -1335,7 +1464,9 @@ tooltipConf: { + #foreach($conf in $el.tooltipConf.keys()) + #set ($value = $el.tooltipConf.get($conf)) #foreach($agg in $aggFunct) @@ -1449,10 +1580,17 @@ formatter: function() { var prepareResult = function(point, result,key){ var chartTemplateSeries = point.series.chart.widgetData.chartTemplate.CHART.VALUES.SERIE; - var series = []; + var series = {}; + var seriesXZ = {}; for (var i=0; i'; result += '' + key +'
'; for(prop in point.tooltipConf){ - if(series.indexOf(prop)>-1 && point.series.name.toLowerCase().indexOf(prop)==-1){ + if(series.hasOwnProperty(prop) && point.series.name.toLowerCase().indexOf(prop)==-1){ delete point.tooltipConf[prop] } if(point.tooltipConf[prop] && point.tooltipConf[prop]!=key){ - result += prop + ': ' + point.tooltipConf[prop]+ '
'; + var valueWithPrecisionAndScale = point.tooltipConf[prop]; + if(series.hasOwnProperty(prop) || seriesXZ.hasOwnProperty(prop)){ + var scale = series.hasOwnProperty(prop) ? series[prop].scaleFactor : seriesXZ[prop].scaleFactor + var precision = series.hasOwnProperty(prop) ? series[prop].precision : seriesXZ[prop].precision + + switch(scale.toUpperCase()) { + + case "EMPTY": + + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale,precision,decimalPoint,thousandsSep); + break; + case "K": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,3),precision,decimalPoint,thousandsSep) + "k"; + break; + case "M": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,6),precision,decimalPoint,thousandsSep) + "M"; + break; + case "G": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,9),precision,decimalPoint,thousandsSep) + "G"; + break; + case "T": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,12),precision,decimalPoint,thousandsSep) + "T"; + break; + case "P": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,15),precision,decimalPoint,thousandsSep) + "P"; + break; + case "E": + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale/Math.pow(10,18),precision,decimalPoint,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + valueWithPrecisionAndScale = Highcharts.numberFormat(valueWithPrecisionAndScale,precision,decimalPoint,thousandsSep); + break; + + } + } + + result += prop + ': ' + valueWithPrecisionAndScale + '
'; + + } } '' @@ -1675,6 +1853,7 @@ }, plotOptions: { + column: {}, series: { cursor: 'pointer', diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/column_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/column_chart.vm index fc8fc83a8e4..89902f790ff 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/column_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/column_chart.vm @@ -802,12 +802,12 @@ #if($xAxis.plotBands.get(0).from=="") from :0, #else - from : $xAxis.plotBands.get(0).from, + from : '$xAxis.plotBands.get(0).from', #end #if($xAxis.plotBands.get(0).to=="") to :0, #else - to : $xAxis.plotBands.get(0).to, + to : '$xAxis.plotBands.get(0).to', #end }, ], @@ -1059,14 +1059,19 @@ #if(($chart.groupSeries && $chart.groupSeries =='true') || ($chart.groupSeriesCateg && $chart.groupSeriesCateg =='true')) #set($enableValues = $chart.VALUES.SERIE.showValue) + #if($chart.VALUES.SERIE.get(0)) #set($relatedSerie = $chart.VALUES.SERIE.get(0)) #if($chart.type.toUpperCase() == 'RADAR' && $chart.groupSeriesCateg && $chart.groupSeriesCateg =='true') - + #if($chart.VALUES.SERIE.get(0).serieTypeRadar && $chart.VALUES.SERIE.get(0).serieTypeRadar!="") #set($relatedSerieTypes = $chart.VALUES.SERIE.get(0).serieTypeRadar.split(", ")) - #set($count = $chart.VALUES.SERIE.get(0).serieTypeRadar.length() - $chart.VALUES.SERIE.get(0).serieTypeRadar.replace(",", "").length()) + #else + #set($relatedSerieTypes = $chart.VALUES.SERIE.get(0).type.split(", ")) + #set($count = $chart.VALUES.SERIE.get(0).type.length() - $chart.VALUES.SERIE.get(0).type.replace(",", "").length()) + #end + #end #set($enableValues = $chart.VALUES.SERIE.get(0).showValue) #end @@ -1103,12 +1108,12 @@ #if($yAxis.plotBands.get(0).from=="") from :0, #else - from : $yAxis.plotBands.get(0).from, + from : '$yAxis.plotBands.get(0).from', #end #if($yAxis.plotBands.get(0).to=="") to :0, #else - to : $yAxis.plotBands.get(0).to, + to : '$yAxis.plotBands.get(0).to', #end }, ], @@ -1141,25 +1146,31 @@ #if($yAxis.min==$yAxis.max) #set ($minAndMaxAreSame= true) #end - #if($yAxis.min && $yAxis.min != "auto" && $yAxis.min!='' ) - #set ($min = $yAxis.min) - min: $yAxis.min, - startOnTick:false, + #if($yAxis.min) + #if($yAxis.min != "auto" && $yAxis.min!='') + #set ($min = $yAxis.min) + min: $yAxis.min, + startOnTick:false, + #elseif($yAxis.min == "auto" || $yAxis.min=='') + min: "$yAxis.min", + #end #end - - #if($yAxis.max && $yAxis.max!='auto' && $yAxis.max!='' && $chartType != "radar") - #set ($max = $yAxis.max) - #if($min) - #if($Integer1.parseInt($min)<$Integer1.parseInt($max)) + #if($yAxis.max) + #if($yAxis.max!='auto' && $yAxis.max!='' && $chartType != "radar") + #set ($max = $yAxis.max) + #if($min) + #if($Integer1.parseInt($min)<$Integer1.parseInt($max)) + max:$yAxis.max, + endOnTick: false, + #end + #else max:$yAxis.max, endOnTick: false, #end - #else - max:$yAxis.max, - endOnTick: false, + #elseif(($yAxis.max == "auto" || $yAxis.max=='') && $chartType != "radar") + max: "$yAxis.max", #end - #end - + #end #if( $chartType == "radar") min:0, #end @@ -1430,7 +1441,9 @@ #end #end { - + label: { + enabled: false + }, #set($relatedSerieColor = false) #set($relatedSerieColor = $relatedSerie.color) #if($relatedSerieColor && $relatedSerieColor != '') @@ -1440,7 +1453,7 @@ name: "$escapeTool.javascript($relatedSerie.name)", #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($relatedSerie.name)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($relatedSerie.name)) color:'$customColor.customValue', #end #end @@ -1472,6 +1485,18 @@ #end type: '$relatedSerieType', #end + + #if($chartType == 'radar') + #if($relatedSerieType == '') + #if($relatedSerie.serieTypeRadar!='') + #set($relatedSerieType = $relatedSerie.serieTypeRadar) + type: '$relatedSerieType', + #end + #else + type: '$relatedSerieType', + #end + #end + #set($styleOfDataLabels = $relatedSerie.dataLabels.style) ## makes the datalabels overlapping @@ -1524,7 +1549,7 @@ #end #end #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($serieCategoryName)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($serieCategoryName)) color:'$customColor.customValue', #end #end @@ -1735,6 +1760,9 @@ { + label: { + enabled: false + }, selected: $selectedValue, initiallySelected: $selectedValue, name: "$escapeTool.javascript($valueKey)", @@ -1759,14 +1787,13 @@ #end #end - #if($relatedSerieTypes && $count!=$counter && $relatedSerieTypes[$counter]) type: '$relatedSerieTypes[$counter]', #set ($counter = $counter+1) #end #* #set ($counter = $counter+1) *# #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($escapeTool.javascript($valueKey))) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($escapeTool.javascript($valueKey))) color:'$customColor.customValue', #end #end @@ -1788,7 +1815,7 @@ #end #end #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($el.name)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($el.name)) color:'$customColor.customValue', #end #end diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/gauge_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/gauge_chart.vm index d835f4dc2cd..b94b86163d4 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/gauge_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/gauge_chart.vm @@ -337,6 +337,8 @@ #if($yAxis.lineColor && $yAxis.lineColor!="") lineColor: '$yAxis.lineColor', ##'#339', + #else + lineColor: '#000000', #end #if($yAxis.tickPosition && $yAxis.tickPosition!="") @@ -359,8 +361,10 @@ offset: $offsetValue, - #if ($yAxis.lineWidth && $yAxis.lineWidth!="") - lineWidth: $yAxis.lineWidth, + #if ($yAxis.lineWidth && $yAxis.lineWidth!="" && $yAxis.lineWidth!=0) + lineWidth: $yAxis.lineWidth, + #else + lineWidth: 1, #end #if ($yAxis.minorTickLength && $yAxis.minorTickLength!="") @@ -550,7 +554,11 @@ { color: "$yAxis.TARGET.get(0).color", dashStyle: "$yAxis.TARGET.get(0).dashStyle", - value: $yAxis.TARGET.get(0).value, + #if($yAxis.TARGET.get(0).value=="") + value :0, + #else + value: '$yAxis.TARGET.get(0).value', + #end width: $yAxis.TARGET.get(0).width, }, ], @@ -670,7 +678,7 @@ #foreach($row in $rows) #set ($serieValue = $row.get($serieColumnsMapped)) - + #if($serieValue!="") { #if($subtype == 'activity') @@ -682,9 +690,10 @@ #set($outer = $innerRadius) innerRadius: $innerRadius +"%", #end - y:$serieValue - }, - + + y:$serieValue + }, + #end #end ], @@ -806,7 +815,9 @@ var value = this.y; var newValue = ""; - + var prefixChar = '${relatedSerie.prefixChar}'; + var postfixChar = '${relatedSerie.postfixChar}'; + var scaleFactor = '${relatedSerie.scaleFactor}'; var decimalPoints = Highcharts.getOptions().lang.decimalPoint; @@ -846,7 +857,8 @@ } - return newValue; + return prefixChar + ' ' + newValue + ' ' + postfixChar; + } }, @@ -864,6 +876,12 @@ #if($seriePostfix) valueSuffix: '$seriePostfix', #end + + #set($serieScaleFactor = $relatedSerie.scaleFactor) + + #if($serieScaleFactor) + valueScaleFactor: '$serieScaleFactor', + #end #if ($relatedSerie.precision) valueDecimals: '$relatedSerie.precision', @@ -932,9 +950,17 @@ tooltip: { + #if($chart.TOOLTIP && $chart.TOOLTIP.borderWidth) + borderWidth: $chart.TOOLTIP.borderWidth, + #end + + #if($chart.TOOLTIP && $chart.TOOLTIP.borderRadius) + borderRadius: $chart.TOOLTIP.borderRadius, + #end + useHTML: true, backgroundColor: null, - borderWidth: 2, + style: { padding: 0 }, @@ -981,6 +1007,7 @@ var valueDecimals = this.series.tooltipOptions.valueDecimals ? this.series.tooltipOptions.valueDecimals : 0; var valuePrefix = this.series.tooltipOptions.valuePrefix ? this.series.tooltipOptions.valuePrefix + ' ' : ''; var valueSuffix = this.series.tooltipOptions.valueSuffix ? ' ' + this.series.tooltipOptions.valueSuffix : ''; + var scaleFactor = this.series.tooltipOptions.valueScaleFactor ? this.series.tooltipOptions.valueScaleFactor : 'empty'; var thisValue = this.y; @@ -993,12 +1020,39 @@ @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ - var decimalPoint = Highcharts.getOptions().lang.decimalPoint, - thousandsSep = Highcharts.getOptions().lang.thousandsSep; - - thisValue = Highcharts.numberFormat(thisValue, valueDecimals, decimalPoint, thousandsSep); - thisValue = valuePrefix + thisValue + valueSuffix; + var decimalPoint = Highcharts.getOptions().lang.decimalPoint, + thousandsSep = Highcharts.getOptions().lang.thousandsSep; + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + thisValue = Highcharts.numberFormat(thisValue,valueDecimals,decimalPoint,thousandsSep); + break; + case "K": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,3),valueDecimals,decimalPoint,thousandsSep) + "k"; + break; + case "M": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,6),valueDecimals,decimalPoint,thousandsSep) + "M"; + break; + case "G": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,9),valueDecimals,decimalPoint,thousandsSep) + "G"; + break; + case "T": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,12),valueDecimals,decimalPoint,thousandsSep) + "T"; + break; + case "P": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,15),valueDecimals,decimalPoint,thousandsSep) + "P"; + break; + case "E": + thisValue = Highcharts.numberFormat(thisValue/Math.pow(10,18),valueDecimals,decimalPoint,thousandsSep) + "E"; + break; + default: + thisValue = Highcharts.numberFormat(thisValue,valueDecimals,decimalPoint,thousandsSep); + break; + + } + thisValue = valuePrefix + thisValue + valueSuffix; + /* Separate font elements (family, size and weight (style)) so the tooltip @@ -1040,8 +1094,10 @@ noData: "$chart.EMPTYMESSAGE.text" }, noData: { + attr: { + zIndex: 10 + }, style:{ - #foreach($styleName in $chart.EMPTYMESSAGE.style.keySet()) fontFamily: '$chart.EMPTYMESSAGE.style.fontFamily', fontSize: '$chart.EMPTYMESSAGE.style.fontSize', color: '$chart.EMPTYMESSAGE.style.color', @@ -1055,7 +1111,6 @@ #elseif($chart.EMPTYMESSAGE.style.fontWeight == 'bold') fontWeight: '$chart.EMPTYMESSAGE.style.fontWeight', #end - #end }, position: { #set ($positionAlign = $chart.EMPTYMESSAGE.position.align) diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/heatmap_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/heatmap_chart.vm index 73b4205a493..f90ccdb7ce0 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/heatmap_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/heatmap_chart.vm @@ -13,13 +13,21 @@ #end #set($columnsNeeded = {}) +#set($columnsNeededOrderType = {}) +#set($columnsNeededOrderColumn = {}) +#set($differentOrdering = false) #set($columnCouter = 0) #foreach($value in $category) - #set($columnsNeeded[$columnCouter] = $value.name) +#set($columnsNeeded[$columnCouter] = $value.name) +#if($value.orderColumn!='' && $value.orderColumn != $value.name) + #set($differentOrdering = true) + #set($columnsNeededOrderColumn[$columnCouter] = $value.orderColumn) +#end +#set($columnsNeededOrderType[$columnCouter] = $value.orderType) - #set($columnCouter = $columnCouter + 1) +#set($columnCouter = $columnCouter + 1) #end ## class java.util.LinkedHashMap - collection when rendering the chart @@ -47,8 +55,8 @@ #set($serieName = $datasettransformer.getSerieName($serie)) #set($columnNames = $datasettransformer.getColumnNames($columnsNeeded)) - #set($firstresult = $datasettransformer.getData($dataRows,$serie,$columnsNeeded,$dataColumnsMapper, $groupingFunction.toLowerCase())) +#set($firstresultOrdering = $datasettransformer.getData($dataRows,$serie,$columnsNeededOrderColumn,$dataColumnsMapper, $groupingFunction.toLowerCase())) #set($firstCategory='') @@ -65,15 +73,30 @@ #else #set($firstCategory = $datasettransformer.getStoreResult($firstresult,$columnsNeeded[0])) - #end ##set($dateresult = $datasettransformer.getDateResult($firstresult,$columnsNeeded[0])) ##set($dummy = $datasettransformer.getStoreResult($firstresult,$columnsNeeded[0])) #set($storeresult = $datasettransformer.getStoreResult($firstresult,$columnsNeeded[1])) +#if($columnsNeededOrderColumn[1]) + #set($storeresultOrder = $datasettransformer.getStoreResult($firstresultOrdering,$columnsNeededOrderColumn[1])) +#end #set($result = $datasettransformer.getResult($firstresult, $serie, $columnsNeeded,$isFirstDate)) +#set($datetype = "string") +#if($isDateTime==true) + #set($datecolumn = $dataFields.get(1).header) + #if($dataFields.get(1).type=="date") + #if($dataFields.get(1).subtype) + #set($datetype = "timestamp") + #else + #set($datetype = "simpledate") + #end + #end +#end + + #set($axisList = $chart.AXES_LIST.AXIS) #set($xAxisList = {}) ## X Axises list container @@ -108,9 +131,10 @@ chart: { type: '$chartType', - dateF: '$chart.dateFormat', - dateT: '$chart.dateTime', - + dateFormat: '$chart.dateFormat', + dateTime: $chart.dateTime, + datetype: '$datetype', + datecolumn: '$datecolumn', #* The zoom in option for HEATMAP chart. User will be able to zoom in on either of those two chart types @@ -158,7 +182,7 @@ outcomingEventsEnabled: $chart.outcomingEventsEnabled, #end - xAxisDate: $isFirstDate, + xAxisDate: $isDateTime, style: { fontFamily: '$chart.style.fontFamily', @@ -302,6 +326,43 @@ #end } }, + tooltip: { + #if($chart.TOOLTIP) + #if($chart.TOOLTIP.borderWidth) + borderWidth: $chart.TOOLTIP.borderWidth, + #end + + #if($chart.TOOLTIP.borderRadius) + borderRadius: $chart.TOOLTIP.borderRadius, + #end + + #if ($chart.TOOLTIP.backgroundColor!="") + backgroundColor: '$chart.TOOLTIP.backgroundColor', + #else + backgroundColor: '#FCFFC5', ## default background color for the serie tooltip + #end + + #if ($chart.TOOLTIP.style.color != '') + color: '$chart.TOOLTIP.style.color' , + #end + + #if ($chart.TOOLTIP.style.align != '') + align: '$chart.TOOLTIP.style.align' , + #end + + #if ($chart.TOOLTIP.style.fontFamily && $chart.TOOLTIP.style.fontFamily != '') + fontFamily: '$chart.TOOLTIP.style.fontFamily' , + #end + + #if ($chart.TOOLTIP.style.fontWeight != '') + fontWeight: '$chart.TOOLTIP.style.fontWeight' , + #end + + #if ($chart.TOOLTIP.style.fontSize != '') + fontSize: '$chart.TOOLTIP.style.fontSize' , + #end + #end + }, #* Property changed from 'symbolWidth' for the former horizontal orientation @@ -356,17 +417,6 @@ }, - tooltip: - { - style: - { - align: '$chart.TOOLTIP.style.align', - fontFamily: '$chart.TOOLTIP.style.fontFamily', - fontSize: '$chart.TOOLTIP.style.fontSize', - fontColor: '$chart.TOOLTIP.style.color' - } - }, - xaxis: { @@ -553,12 +603,22 @@ categoryGroupBy: '$category[1].column', firstCategory: $firstCategory, storeresult: $storeresult, + #if($storeresultOrder) + storeresultOrder: $storeresultOrder, + #end + differentOrdering: $differentOrdering, + secondColumnOrder: '$columnsNeededOrderType[1]', serie: $serieName, #if($serieObj.precision) precision: "$serieObj.precision", #else precision: "", #end + #if($serieObj.scaleFactor) + scaleFactor: "$serieObj.scaleFactor", + #else + scaleFactor: "empty", + #end #if($serieObj.prefixChar) prefixChar: "$serieObj.prefixChar", #else @@ -569,7 +629,7 @@ #else postfixChar: "", #end - columns: $columnNames + columns: $columnNames, }, #* diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/pie_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/pie_chart.vm index 1b059734b85..48f0ae63f43 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/pie_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/pie_chart.vm @@ -530,7 +530,7 @@ { #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($relatedSerie.name)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($relatedSerie.name)) color:'$customColor.customValue', #end #end @@ -1112,7 +1112,7 @@ y:null, #end #foreach($customColor in $customColors) - #if($customColor.customName.equalsIgnoreCase($serieName)) + #if($escapeTool.javascript($customColor.customName).equalsIgnoreCase($serieName)) color:'$customColor.customValue', #end #end @@ -1321,7 +1321,7 @@ } if(showAbsValueTooltip && showPercentageTooltip){ thisValuePercentage = Highcharts.numberFormat(thisValuePercentage, valueDecimals, decimalPoint, thousandsSep); - thisValue = valuePrefix + thisValuePercentage +"%"+ valueSuffix+ " ("+thisValue+")" + thisValue = valuePrefix + thisValue + valueSuffix+ " ("+thisValuePercentage+"%)" } else if(!showAbsValueTooltip && showPercentageTooltip){ thisValue = ""; thisValuePercentage = Highcharts.numberFormat(thisValuePercentage, valueDecimals, decimalPoint, thousandsSep); @@ -1452,7 +1452,7 @@ if(showAbsValueTooltip && showPercentageTooltip){ thisValuePercentage = Highcharts.numberFormat(this.percentage, precision, decimalPoint, separatorOfThousands); - thisValue = valuePrefix + thisValuePercentage +"%"+ valueSuffix+ " ("+thisValue+")" + thisValue = valuePrefix + thisValue + valueSuffix+ " ("+thisValuePercentage+ "%)" } else if(!showAbsValueTooltip && showPercentageTooltip){ thisValue = ""; thisValuePercentage = Highcharts.numberFormat(this.percentage, precision, decimalPoint, separatorOfThousands); diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/scatter_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/scatter_chart.vm index 2fb62cd8825..7a0d9a140a5 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/scatter_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/scatter_chart.vm @@ -513,12 +513,12 @@ #if($xAxis.plotBands.get(0).from=="") from :0, #else - from : $xAxis.plotBands.get(0).from, + from : '$xAxis.plotBands.get(0).from', #end #if($xAxis.plotBands.get(0).to=="") to :0, #else - to : $xAxis.plotBands.get(0).to, + to : '$xAxis.plotBands.get(0).to', #end }, ], @@ -692,12 +692,12 @@ #if($yAxis.plotBands.get(0).from=="") from :0, #else - from : $yAxis.plotBands.get(0).from, + from : '$yAxis.plotBands.get(0).from', #end #if($yAxis.plotBands.get(0).to=="") to :0, #else - to : $yAxis.plotBands.get(0).to, + to : '$yAxis.plotBands.get(0).to', #end }, ], diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/sunburst_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/sunburst_chart.vm index 60631074638..c13d5a14aba 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/sunburst_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/sunburst_chart.vm @@ -35,6 +35,7 @@ #end #set($serieName = $chart.VALUES.SERIE.name) +#set($serie = $chart.VALUES.SERIE) #set($groupingFunction = $chart.VALUES.SERIE.groupingFunction) #set($result = $datasettransformer.createTreeChart($columnsNeeded,$serieName,$dataColumnsMapper,$dataRows,$groupingFunction.toLowerCase())) @@ -184,6 +185,43 @@ #end } }, + tooltip: { + #if($chart.TOOLTIP) + #if($chart.TOOLTIP.borderWidth) + borderWidth: $chart.TOOLTIP.borderWidth, + #end + + #if($chart.TOOLTIP.borderRadius) + borderRadius: $chart.TOOLTIP.borderRadius, + #end + + #if ($serie.TOOLTIP.backgroundColor!="") + backgroundColor: '$serie.TOOLTIP.backgroundColor', + #else + backgroundColor: '#FCFFC5', ## default background color for the serie tooltip + #end + + #if ($serie.TOOLTIP.style.color != '') + color: '$serie.TOOLTIP.style.color' , + #end + + #if ($serie.TOOLTIP.style.align != '') + align: '$serie.TOOLTIP.style.align' , + #end + + #if ($serie.TOOLTIP.style.fontFamily && $serie.TOOLTIP.style.fontFamily != '') + fontFamily: '$serie.TOOLTIP.style.fontFamily' , + #end + + #if ($serie.TOOLTIP.style.fontWeight != '') + fontWeight: '$serie.TOOLTIP.style.fontWeight' , + #end + + #if ($serie.TOOLTIP.style.fontSize != '') + fontSize: '$serie.TOOLTIP.style.fontSize' , + #end + #end + }, title: { @@ -236,18 +274,17 @@ style: { - fontFamily: '$chart.TIP.style.fontFamily', - fontSize: '$chart.TIP.style.fontSize', - color: '$chart.TIP.style.color', - width: '$chart.TIP.style.width', + #foreach($styleName in $chart.TIP.style.keySet()) + #set ($styleValue = $chart.TIP.style[$styleName]) + #if ($styleName == 'fontWeight' && ($styleValue == 'italic' || $styleValue == 'normal')) + fontStyle: '$styleValue', + #elseif($styleName == 'fontWeight' && $styleValue == 'underline') + textDecoration: 'underline', + #else + $styleName: '$styleValue', + #end + #end - #if($chart.TIP.style.fontWeight == 'italic' || $chart.TIP.style.fontWeight == 'normal') - fontStyle: '$chart.TIP.style.fontWeight', - #elseif($chart.TIP.style.fontWeight == 'underline') - textDecoration: '$chart.TIP.style.fontWeight', - #elseif($chart.TIP.style.fontWeight == 'bold') - fontWeight: '$chart.TIP.style.fontWeight', - #end }, }, diff --git a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/treemap_chart.vm b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/treemap_chart.vm index 2d3c7a4c5d6..f908395aa33 100644 --- a/knowagecockpitengine/src/main/resources/chart/templates/highcharts/treemap_chart.vm +++ b/knowagecockpitengine/src/main/resources/chart/templates/highcharts/treemap_chart.vm @@ -99,7 +99,6 @@ #* Provide enough space for the "Back" button. *# - marginBottom: 40, ## I think this is necessary when title and subtitle are not provided (danristo) #if ($chart.TITLE.text == "" && $chart.SUBTITLE.text == "") @@ -210,6 +209,17 @@ #end } }, + tooltip: { + #if($chart.TOOLTIP) + #if($chart.TOOLTIP.borderWidth) + borderWidth: $chart.TOOLTIP.borderWidth, + #end + + #if($chart.TOOLTIP.borderRadius) + borderRadius: $chart.TOOLTIP.borderRadius, + #end + #end + }, #* Remove credits from the TREEMAP chart (the "Highcharts.com" link at the @@ -302,6 +312,11 @@ #else precision: "", #end + #if($serie.scaleFactor) + scaleFactor: "$serie.scaleFactor", + #else + scaleFactor: "empty", + #end #if($serie.prefixChar) prefixChar: "$serie.prefixChar", #else @@ -322,7 +337,33 @@ #else showPercentage:false, #end - + tooltip: { + #if ($serie.TOOLTIP.backgroundColor!="") + ttBackColor: '$serie.TOOLTIP.backgroundColor', + #else + ttBackColor: '#FCFFC5', ## default background color for the serie tooltip + #end + + #if ($serie.TOOLTIP.style.color != '') + ttColor: '$serie.TOOLTIP.style.color' , + #end + + #if ($serie.TOOLTIP.style.align != '') + ttAlign: '$serie.TOOLTIP.style.align' , + #end + + #if ($serie.TOOLTIP.style.fontFamily && $serie.TOOLTIP.style.fontFamily != '') + ttFont: '$serie.TOOLTIP.style.fontFamily' , + #end + + #if ($serie.TOOLTIP.style.fontWeight != '') + ttFontWeight: '$serie.TOOLTIP.style.fontWeight' , + #end + + #if ($serie.TOOLTIP.style.fontSize != '') + ttFontSize: '$serie.TOOLTIP.style.fontSize' , + #end + }, }, plotOptions: { diff --git a/knowagecockpitengine/src/main/resources/ehcache.xml b/knowagecockpitengine/src/main/resources/ehcache.xml new file mode 100644 index 00000000000..33aec37e2e9 --- /dev/null +++ b/knowagecockpitengine/src/main/resources/ehcache.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file diff --git a/knowagecockpitengine/src/main/resources/log4j.properties b/knowagecockpitengine/src/main/resources/log4j.properties index 1516378b8b3..22a3129abbe 100644 --- a/knowagecockpitengine/src/main/resources/log4j.properties +++ b/knowagecockpitengine/src/main/resources/log4j.properties @@ -26,4 +26,4 @@ log4j.additivity.it.eng.spagobi.commons.utilities.messages=false log4j.logger.it.eng.spagobi.commons.utilities.urls.WebUrlBuilder=ERROR, FILE log4j.additivity.it.eng.spagobi.commons.utilities.urls.WebUrlBuilder=false -log4j.logger.it.eng.knowage.engine.cockpit.api.export=WARN, FILE +log4j.logger.it.eng.knowage.engine.cockpit.api.export=WARN, FILE \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/META-INF/context.xml b/knowagecockpitengine/src/main/webapp/META-INF/context.xml index cdbd611522d..7989535822e 100644 --- a/knowagecockpitengine/src/main/webapp/META-INF/context.xml +++ b/knowagecockpitengine/src/main/webapp/META-INF/context.xml @@ -10,5 +10,5 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/chart/designer/chartImport.jsp b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/chart/designer/chartImport.jsp index 9f7184f7086..226d57f6186 100644 --- a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/chart/designer/chartImport.jsp +++ b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/chart/designer/chartImport.jsp @@ -41,10 +41,17 @@ along with this program. If not, see . + - + + + + + + - + + diff --git a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index a7192a31357..3688752c351 100644 --- a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -124,6 +124,8 @@ END-PRODUCTION --> + + diff --git a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/cockpitImport.jsp b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/cockpitImport.jsp index 9ad2deeacd9..13f5b8f8b0e 100644 --- a/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/cockpitImport.jsp +++ b/knowagecockpitengine/src/main/webapp/WEB-INF/jsp/commons/angular/cockpitImport.jsp @@ -39,8 +39,11 @@ along with this program. If not, see . + + + @@ -88,11 +91,18 @@ along with this program. If not, see . + + + + + + + diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/chartInitializer/services/highchartsInitializerService.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/chartInitializer/services/highchartsInitializerService.js index ddf04cb34a9..33310874067 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/chartInitializer/services/highchartsInitializerService.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/chartInitializer/services/highchartsInitializerService.js @@ -23,9 +23,37 @@ angular.module('chartInitializer') this.chart = null; var chartConfConf = null; + this.changeDatasetColumns = function(chartConf, data){ + for (var attrname in chartConf) { + if(!(typeof chartConf[attrname] == 'object')){ + if(typeof chartConf[attrname] =='string') + chartConf[attrname] = chartConf[attrname].replace(/(\$F\{)([a-zA-Z0-9\-\_\s]*)(\})/g,function(match,p1,p2){ + var column = ""; + for (var j = 1; j < data.metaData.fields.length; j++) { + if(data.metaData.fields[j].header.startsWith(p2)){ + column = data.metaData.fields[j].name + } + } + return data.rows[0][column]; + }) + } else { + this.changeDatasetColumns(chartConf[attrname],data); + } + } + } this.renderChart = function(renderObj, jsonData){ + if(jsonData ){ + if(jsonData.jsonData) { + var data = JSON.parse(jsonData.jsonData); + } else if(jsonData.rows){ + var data = jsonData; + } + if(data && data.rows.length>0){ + this.changeDatasetColumns(renderObj.chartConf,data); + } + } var chartConf = renderObj.chartConf; if(chartConf.chart.additionalData && chartConf.chart.additionalData.dateTime && chartConf.chart.additionalData.datetype!="string"){ for (var i = 0; i < chartConf.series.length; i++) { @@ -112,29 +140,52 @@ angular.module('chartInitializer') var finalMin = Math.min.apply(Math, [mapAxis.min[i], plotBands && plotBands[0].from != plotBands[0].to ? plotBands[0].from : mapAxis.min[i], plotLines && plotLines[0].width > 0 ? plotLines[0].value : mapAxis.min[i]].map(function(o) { return o; })); var finalMax = Math.max.apply(Math, [mapAxis.max[i], plotBands && plotBands[0].to != plotBands[0].from ? plotBands[0].to : mapAxis.max[i], plotLines && plotLines[0].width > 0 ? plotLines[0].value : mapAxis.max[i]].map(function(o) { return o; })); - if(chartConf.yAxis[i].min==undefined){ + if(chartConf.yAxis[i].min===undefined || chartConf.yAxis[i].min=='auto'){ chartConf.yAxis[i].min = finalMin>=0 ? finalMin * 0.5 : finalMin * 1.5; } finalMin = chartConf.yAxis[i].min; - if(chartConf.yAxis[i].max==undefined){ + if(chartConf.yAxis[i].min=="") chartConf.yAxis[i].min = null; + if(chartConf.yAxis[i].max===undefined || chartConf.yAxis[i].max=='auto') { chartConf.yAxis[i].max = finalMax>=0 ? finalMax * 1.1 : finalMax * 0.9; } finalMax = chartConf.yAxis[i].max + if(chartConf.yAxis[i].max=="") chartConf.yAxis[i].max = null; infoFroDrill.push({"min":finalMin,"max":finalMax,"plotBands":plotBands,"plotLines":plotLines}) } isBasic = true; } + if( chartType == 'gauge'){ + for (var i =0; i < chartConf.yAxis.length; i++){ + var mapAxis = this.setExtremes(chartConf); + var finalMin = mapAxis.min[i]; + var finalMax = mapAxis.max[i]; + if(chartConf.yAxis[i].min == chartConf.yAxis[i].max){ + chartConf.yAxis[i].min = finalMin>=0 ? Math.round(finalMin * 0.5) : Math.round(finalMin * 1.5) + chartConf.yAxis[i].max = finalMax>=0 ? Math.round(finalMax * 1.1) : Math.round(finalMax * 0.9); + } + + } + + } + if(chartConf.plotOptions && chartConf.plotOptions.column && chartConf.plotOptions.column.stacking) { + for (var i =0; i < chartConf.yAxis.length; i++){ + if(chartConf.yAxis[i].min !=undefined && (chartConf.yAxis[i].min == 'auto' || chartConf.yAxis[i].min=='')) delete chartConf.yAxis[i].min + + if(chartConf.yAxis[i].max !=undefined && (chartConf.yAxis[i].max == 'auto' || chartConf.yAxis[i].max=='')) delete chartConf.yAxis[i].max + } + } chartConfMergeService.addProperty(renderObj.chartTemplate.advanced,chartConf); - if(renderObj.chartTemplate.groupSeriesCateg && - renderObj.chartTemplate.VALUES.CATEGORY.drillOrder[renderObj.chartTemplate.VALUES.CATEGORY.groupby]!=undefined && + if(renderObj.chartTemplate.groupSeriesCateg && renderObj.chartTemplate.VALUES.CATEGORY.drillOrder!=undefined && + renderObj.chartTemplate.VALUES.CATEGORY.drillOrder[renderObj.chartTemplate.VALUES.CATEGORY.groupby]!=undefined && renderObj.chartTemplate.VALUES.CATEGORY.drillOrder[renderObj.chartTemplate.VALUES.CATEGORY.groupby].orderColumn == renderObj.chartTemplate.VALUES.CATEGORY.groupby){ var orderType = renderObj.chartTemplate.VALUES.CATEGORY.drillOrder[renderObj.chartTemplate.VALUES.CATEGORY.groupby].orderType == "desc" ? 'desc' : 'asc'; if(orderType=='asc') sortAsc(chartConf.series); else sortDesc(chartConf.series); } + this.chart = new Highcharts.Chart(chartConf); if(isBasic){ this.chart.extremes = infoFroDrill; @@ -352,10 +403,10 @@ angular.module('chartInitializer') top; if (checkbox) { top = translateY + titleHeight + checkbox.y + - (this.scrollOffset || 0) + 3; + (this.scrollOffset || 0); css(checkbox, { left: (alignAttr.translateX + item.checkboxOffset + - checkbox.x - groupW) + 'px', + checkbox.x - groupW - 40) + 'px', top: top + 'px', display: this.proximate || ( top > translateY - 6 && @@ -640,8 +691,8 @@ angular.module('chartInitializer') if(chart.userOptions.chart.type!="pie" && !chart.userOptions.plotOptions.column.stacking){ setTimeout(function () { chart.yAxis[indexOfAxis].update({ - max: chart.breadcrumb[chart.breadcrumb.length-1] ? storeMinAndMax[chart.breadcrumb[chart.breadcrumb.length-1].selectedName].max : chart.extremes[indexOfAxis].max, - min: chart.breadcrumb[chart.breadcrumb.length-1] ? storeMinAndMax[chart.breadcrumb[chart.breadcrumb.length-1].selectedName].min : chart.extremes[indexOfAxis].min, + max: chart.breadcrumb[chart.breadcrumb.length-1] ? storeMinAndMax[chart.breadcrumb[chart.breadcrumb.length-1].selectedName].max : chart.extremes[indexOfAxis].max != "" ? chart.extremes[indexOfAxis].max : null, + min: chart.breadcrumb[chart.breadcrumb.length-1] ? storeMinAndMax[chart.breadcrumb[chart.breadcrumb.length-1].selectedName].min : chart.extremes[indexOfAxis].min != "" ? chart.extremes[indexOfAxis].min : null, }); if(!chart.breadcrumb[chart.breadcrumb.length-1]) { delete chart.drilledSerie diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Chord.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Chord.js index 4ec84e27cb1..6cb14c1a6a2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Chord.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Chord.js @@ -4,45 +4,45 @@ Released under the GNU General Public License, version 3.*/ /** * The rendering function for the PARALLEL chart. * @param jsonData JSON containing data (parameters) about the chart. - * @param locale Information about the locale (language). Needed for the formatting of the series values (data labels and tooltips). + * @param locale Information about the locale (language). Needed for the formatting of the series values (data labels and tooltips). * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCrossNavigationTo) { /** - * 'opacityMouseOver' - value for the opacity of the item (row) that is covered by the mouse pointer and all the items + * 'opacityMouseOver' - value for the opacity of the item (row) that is covered by the mouse pointer and all the items * that are linked (connected) to that row (item) - * - * 'opacityMouseOutAndDefault' - value of the opacity of all graphical items (arcs and stripes) when non of the items + * + * 'opacityMouseOutAndDefault' - value of the opacity of all graphical items (arcs and stripes) when non of the items * (rows) is selected by the mouse pointer or when the mouse pointer leaves an item */ // TODO: Maybe customizable ??? var opacityMouseOutAndDefault = 0.6; var opacityMouseOver = 0.1; - + /** * 'allFieldsObject' - object that contains information about the data that we got from the server. Particularly we get * data about the rows and columns that our matrix (will) contain - * + * * 'allFieldsArray' - array of all rows/columns items (fields) sorted in alphabetically ascending order that matrix (will) * contain. This way can sort all rows and columns of the future matrix in the same, alphabetically ascending, order */ var allFieldsObject = jsonData.data[0].metaData.fields; var allFieldsArray = new Array(); - + /** * 'columnsPairedWithRows' - contains data about which columns are linked to the particular row, that is, which column is in - * the intersection with the particular row and what is the value of their intersection (the value of the matrix field). We - * will need this data to see outgoing items (columns to which particular row is connected). - * + * the intersection with the particular row and what is the value of their intersection (the value of the matrix field). We + * will need this data to see outgoing items (columns to which particular row is connected). + * * 'rowsPairedWithColumns' - containes data about which rows are connected to the particular column (we will need this data * in pair woth the previous one - columnsPairedWithRows). We will need this to see incoming items (which rows (items) are * connected to the particular item (in this case, column)) */ - var columnsPairedWithRows = new Array(); + var columnsPairedWithRows = new Array(); var rowsPairedWithColumns = new Array(); - + /** * TODO: NOT USED: Useful when filtering is enabled (FILTER tags attribute 'value' is set to 'true') */ @@ -66,20 +66,20 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro } return -1; } - + /** * Returns an array of tick angles and labels, given a group. - * + * * Modified so it can set an unique tick density for any CHORD chart document * (no matter how big numbers on arcs are - kilos, millions and so on). Also * the frequency of appearance of numeric labels on those arcs is set so they * are equidistant. * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ - function groupTicks(d) - { + function groupTicks(d) + { var k = (d.endAngle - d.startAngle) / d.value; - + /** * What will be a value by a single tick (value that distance between two * subsequent ticks represents). This way we will split ticks so that we @@ -88,44 +88,44 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * an uniformly organized charts. */ var valueByTick = Math.floor(totalValueOnArcs/360); - + /** - * The index that represents a letter in the "suffixes" array, so it + * The index that represents a letter in the "suffixes" array, so it * replicates the suffix degree of a number. E.g. suffixNum=1 represents * kilos, since it will take the 1th element in the "suffixes" array. */ var suffixNum = 0; - + var suffixes = ["", "k" , "M" , "G" , "T" , "P" , "E"]; - + /** * The precision that numerical label values will have (number of decimals * behind the whole value of the number). */ var precision = 2; var precisPoweredValue = Math.pow(10,precision); - + var suffixNumPoweredValue = 0; - + /** * Divide current arc on as many tick we have for it, so that every tick * will have an offset of 'valuByTick' value. */ - return d3.range(0, d.value, valueByTick).map(function(v, i) { - + return d3.range(0, d.value, valueByTick).map(function(v, i) { + /** * If the value of the current tick, 'v', is greater then 1000 (1k), * analyze the value in order to figure out what is the appropriate - * suffix that numeric label value will contain (show) - k, M, G and + * suffix that numeric label value will contain (show) - k, M, G and * so on. */ if (v >= 1000) { suffixNum = Math.floor((v + "").length/3); - + /** * If the number of numerals inside the current tick value is - * a while multiple of number 3 (3, 6, 9 and so on), consider + * a while multiple of number 3 (3, 6, 9 and so on), consider * it as a number that belongs to the previous numerical suffix. * E.g. if the 'v' is 999555, we will consider it as a 999.55k, * hence we will not use the mega (M) suffix, but rather kilo @@ -133,120 +133,120 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro */ if ((v + "").length%3 === 0) { suffixNum--; - } + } } - + suffixNumPoweredValue = Math.pow(1000,suffixNum); - + return { - + startAngle: d.startAngle, endAngle: d.endAngle, angle: v * k + d.startAngle, - label: i % 10 ? null : Math.round(parseFloat(v / suffixNumPoweredValue)*precisPoweredValue)/precisPoweredValue + "" + suffixes[suffixNum] - + label: i % 10 ? null : Math.round(parseFloat(v / suffixNumPoweredValue)*precisPoweredValue)/precisPoweredValue + "" + suffixes[suffixNum] + }; }); } - + /** - * 'deselectClickedItem' - indicator if user clicked on some item on the chart - if false, prevent mouse over + * 'deselectClickedItem' - indicator if user clicked on some item on the chart - if false, prevent mouse over * and mouse out events. If true every item on the chart should be deselected - fully colored - * + * * 'indexOfItemSelected' - index of the item of the chart that is selected. We need this parameter to take care * if we should */ var deselectClickedItem = undefined; var indexOfItemSelected = -1; var previouslySelected = false; - + var selectedSomeItem = false; var indexOfSelectedItem = -1; var enableMouseOver = true; var enableMouseOut = true; var enableOtherSelect = false; - + /** * Returns an event handler for fading a given chord group. */ function fadeMouseOver() - { + { return function(g, i) { - + setParamsClickAndMouseOver(g,i,false); - + /** - * With filtering we are getting pairs of stripes: one member of the pair is the source item (the row) whose + * With filtering we are getting pairs of stripes: one member of the pair is the source item (the row) whose * outgoing stripe(s) we need to leave as default color (darker); the second member of the pair is the target - * item's stripe (both linking two items: source and target) that is coming into the source item (the row). + * item's stripe (both linking two items: source and target) that is coming into the source item (the row). * We also need to leave this, target item's stripe as default color (darker). - * + * * The same logic, just in other direction is for this part inside the 'fadeMouseOut' function - those stripes * (that we mentioned in previous paragraph) need to be reset as default color (dark) except those that are the * subject of our discussion: the soure and target item's stripe (links between them). */ if (enableMouseOver) - { + { svg.selectAll(".chord path") .filter(function(d) { return d.source.index != i && d.target.index != i; }) .transition() - .style("opacity", opacityMouseOver); - + .style("opacity", opacityMouseOver); + var tool=printTheResultWhenSelecting(i); - + tooltip. // attr("hidden","false"). transition().duration(50).style("opacity","1"); //tooltip.style("background",myColors(d[groupcolumn])); var ttText = tooltip.html(tool); - + /** - * Call the function that enables positioning of the + * Call the function that enables positioning of the * tooltip according to its dimensions. - */ + */ var chartHeight = jsonData.chart.height ? Number(jsonData.chart.height) : panel.offsetHeight; var chartWidth = jsonData.chart.width ? Number(jsonData.chart.width) : panel.offsetWidth; - - positionTheTooltip(d3.event.layerX,d3.event.layerY,ttText); - -// .style("left", (d3.event.pageX) + "px") + + positionTheTooltip(d3.event.layerX,d3.event.layerY,ttText); + +// .style("left", (d3.event.pageX) + "px") // .style("top", (d3.event.pageY- 25) + "px"); - + } } } - + function fadeMouseOut() { - return function(g, i) - { + return function(g, i) + { setParamsClickAndMouseOver(g,i,false); - + if (enableMouseOut) { svg.selectAll(".chord path") .filter(function(d) { return d.source.index != i && d.target.index != i; }) .transition() .style("opacity", opacityMouseOutAndDefault); - + tooltip. // attr("hidden","false"). transition().duration(50).style("opacity","0"); //tooltip.style("background",myColors(d[groupcolumn])); - - - } + + + } }; } function clickOnItem() - { - - return function(g, i) - { - + { + + return function(g, i) + { + setParamsClickAndMouseOver(g,i,true); - + /** * Reset all stripes to the default (mouse out, darker) color. */ @@ -254,21 +254,21 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .filter(function(d) { return true; }) .transition() .style("opacity", opacityMouseOutAndDefault); - + /** - * Find the one (stripes that link target and source items) that we need to leave as default + * Find the one (stripes that link target and source items) that we need to leave as default * (darker, mouse out) color. Other stripes will be shadowed (lighter (mouse over) color). */ svg.selectAll(".chord path") .filter(function(d) { return d.source.index != i && d.target.index != i; }) .transition() .style("opacity", opacityMouseOver); - + tooltip.transition().duration(50).style("opacity","0"); - + if(jsonData.chart.isCockpit==true){ if(jsonData.chart.outcomingEventsEnabled){ - + paramethers=crossNavigationParamethers(jsonData.data[0].rows[i]); // var selectParams={ // categoryName:paramethers.categoryName, @@ -276,12 +276,12 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro // serieName:paramethers.serieName, // serieValue:paramethers.serieValue, // groupingCategoryName:paramethers.groupingCategoryName, -// groupingCategoryValue:paramethers.groupingCategoryValue +// groupingCategoryValue:paramethers.groupingCategoryValue // }; var selectParams={}; category= jsonData.categories[1].value; selectParams[category]=paramethers.CATEGORY_VALUE; - + handleCockpitSelection(selectParams); } }else if(jsonData.crossNavigation.hasOwnProperty('crossNavigationDocumentName')){ @@ -303,9 +303,9 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ else { - + /** - * Collect all needed data for the cross-navigation (all output parameters for the CHORD chart document) and + * Collect all needed data for the cross-navigation (all output parameters for the CHORD chart document) and * forward them towards the cross-navigation handler. * NOTE: output parameters as series item name and category name are not taken into count at this time instance. */ @@ -313,14 +313,14 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro navigParams["CATEGORY_NAME"] = jsonData.categories[0].value; navigParams["SERIE_NAME"] = jsonData.series.name; handleCrossNavigationTo(navigParams,"CHORD"); - + } - + }; } - + function crossNavigationParamethers(d){ - + /** * Only four output paramters needed for the CHORD chart type (namely, no need for GROUPING_NAME and GROUPING_VALUE - not used). * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) @@ -331,49 +331,49 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro "SERIE_NAME":null, "SERIE_VALUE":null }; - + param.CATEGORY_VALUE=d.column_0; - + serie=0; - + for(property in d){ if(property != "column_0"){ serie=serie+d[property]; } } - - param.SERIE_VALUE=serie; - + + param.SERIE_VALUE=serie; + return param; } - - + + /** * Set parameters that are necessary for the events that we are listening to: the mouse over and click event. - * According to these parameters we are going to control when should we enable or disable listening to the + * According to these parameters we are going to control when should we enable or disable listening to the * mouse over and/or mouse out events. */ function setParamsClickAndMouseOver(d,i,isClick) { - + /** * The function responsible for processing the 'click' event listener's call is calling this function. * This function is not called by the 'fadeMouseOver'/'fadeMouseOut' functions that are responsible * for processing the 'mouseover'/'mouseout' event listener's call. */ if (isClick) - { + { enableMouseOver = false; - + /** * No item is selected (clicked) on the chart - select it and freeze the chart. */ if (selectedSomeItem == false) { - selectedSomeItem = true; - enableMouseOut = false; - indexOfSelectedItem = i; - + selectedSomeItem = true; + enableMouseOut = false; + indexOfSelectedItem = i; + /** * TODO: * Temporary function for printing out the items (source and target) that are the @@ -384,7 +384,7 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro /** * Some item is already selected (the chart is still freeze). */ - else + else { /** * The item that is now clicked (selected) is already selected, hence we need to deselect it and @@ -392,9 +392,9 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro */ if (indexOfSelectedItem == i) { - selectedSomeItem = false; - enableMouseOut = true; - indexOfSelectedItem = -1; + selectedSomeItem = false; + enableMouseOut = true; + indexOfSelectedItem = -1; } /** * The item that we have now clicked (selected) is different for the one that is alreday selected, @@ -402,10 +402,10 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro */ else { - selectedSomeItem = true; - enableMouseOut = false; - indexOfSelectedItem = i; - + selectedSomeItem = true; + enableMouseOut = false; + indexOfSelectedItem = i; + //printTheResultWhenSelecting(i); } } @@ -414,147 +414,147 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * This function is called by the 'fadeMouseOver'/'fadeMouseOut' functions that are responsible * for processing the 'mouseover'/'mouseout' event listener's call. */ - else + else { /** - * if-block: + * if-block: * None of items (arcs) is selected (clicked) - the chart us 'unfreeze' * else-block: * Some item (arc) is selected (clicked) - the chart is 'freeze' */ - if (selectedSomeItem == false) + if (selectedSomeItem == false) { - enableMouseOver = true; - enableMouseOut = true; + enableMouseOver = true; + enableMouseOut = true; } else { - enableMouseOver = false; - enableMouseOut = false; - } + enableMouseOver = false; + enableMouseOut = false; + } } } - + /** * @author Ana Tomic * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ function printTheResultWhenSelecting(i) { - // With which columns is this (selected, clicked) row paired + // With which columns is this (selected, clicked) row paired //console.log(columnsPairedWithRows[i]); - // Which columns are paired with this (selected, clicked) row + // Which columns are paired with this (selected, clicked) row // console.log(rowsPairedWithColumns[i]); - + var ttp="" + columnsPairedWithRows[i].row + ""+ "

"+"To:"; - + for(j=0;jFrom: "; - + for(j=0;j panel.offsetHeight && width==panel.offsetWidth) { widthCorrection = 16; overflowXHidden = "hidden"; } - + if (!jsonData.chart.isCockpit && width > panel.offsetWidth && height==panel.offsetHeight) { heightCorrection = 16; overflowYHidden = "hidden"; } - + width -= widthCorrection; height -= heightCorrection; - + var chartDivWidth=width; var chartDivHeight=height; var heightForChartSvg = height; - + if(jsonData.title.text!="" || jsonData.subtitle.text!=""){ - + emptySplitDivHeight=10; - + chartDivHeight-=Number(removePixelsFromFontSize(jsonData.title.style.fontSize))*1.2; chartDivHeight-=Number(removePixelsFromFontSize(jsonData.subtitle.style.fontSize))*1.2; chartDivHeight-=emptySplitDivHeight*1.2; - + heightForChartSvg = height-(Number(removePixelsFromFontSize(jsonData.title.style.fontSize)) + Number(removePixelsFromFontSize(jsonData.subtitle.style.fontSize)) +emptySplitDivHeight)*1.2; - + } - + var innerRadius = Math.min(width,height) * .35; var outerRadius = innerRadius * 1.1; - + /** * Number of row/column elements of the squared martix */ var elemSize = jsonData.data[0].results; - + var colors; if(jsonData.colors.length > 0){ colors=jsonData.colors; }else{ colors=getDefaultColorPalette(); } - + var fill = d3.scale.ordinal() .domain(d3.range(elemSize)) .range(colors); - + var randomId= Math.round((Math.random())*10000); - + //-- mainPanelTemp.setStyle("overflow-y","hidden"); -- - + /** * Create an invisible HTML form that will sit on the page where the chart (in this case, the CHORD) is rendered. * This form will serve us as a media through which the data and customization for the rendered chart will be sent - * towards the Highcharts exporting service that will take the HTML of the CHORD chart, render it and take a snapshot + * towards the Highcharts exporting service that will take the HTML of the CHORD chart, render it and take a snapshot * that will be sent back towards the client (our browser) in a proper format (PDF or PNG) and downloaded to the local * machine. - * - * This way, when the user clicks on the export option for the rendered chart, the JS code ("chartExecutionController.js") - * that fills the form (that we set here as a blank structure) will eventually submit it towards the Highcharts export + * + * This way, when the user clicks on the export option for the rendered chart, the JS code ("chartExecutionController.js") + * that fills the form (that we set here as a blank structure) will eventually submit it towards the Highcharts export * service. The result is the exported chart. This code will catch the form by the ID that we set here. - * + * * (migration from the ExtJS execution to AngularJS) - * + * * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ - + if (allFieldsObject.length < 1) { var emptyMsgFontSize = parseInt(jsonData.emptymessage.style.fontSize); //var emptyMsgTotal = emptyMsgDivHeight+emptyMsgFontSize/2; var emptyMsgTotal = emptyMsgFontSize; - + + var emptyMsgAlignment = null; + if(jsonData.emptymessage.style.align == "left") { + emptyMsgAlignment = "flex-start"; + } else if (jsonData.emptymessage.style.align == "right") { + emptyMsgAlignment = "flex-end"; + } else { + emptyMsgAlignment = "center"; + } + // Set empty text on the chart d3.select(panel) .style("color",jsonData.emptymessage.style.color) - .style("text-align",jsonData.emptymessage.style.align) + .style("display","flex") + .style("align-items","center") + .style("justify-content",emptyMsgAlignment) .style("font-family",jsonData.emptymessage.style.fontFamily) .style("font-style",jsonData.emptymessage.style.fontStyle) .style("font-weight",jsonData.emptymessage.style.fontWeight) .style("text-decoration",jsonData.emptymessage.style.textDecoration) .style("font-size",emptyMsgFontSize) - .text(jsonData.emptymessage.text); + .text(jsonData.emptymessage.text); } else { + panel.innerText = ''; d3.select(panel) .append("form").attr("id","export-chart-form").style("margin","0px") .append("input").attr("type","hidden").attr("name","options") @@ -683,11 +695,11 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .append("input").attr("type","hidden").attr("name","async") .append("input").attr("type","hidden").attr("name","chartHeight") .append("input").attr("type","hidden").attr("name","chartWidth"); - + /** * The body inside of which the chart will be rendered. * @commentBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ + */ d3.select(panel) .style("overflow-x",overflowXHidden) .style("overflow-y",overflowYHidden) @@ -696,7 +708,7 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .attr("class","d3chartclass") .style("margin","auto") // Center chart horizontally (Danilo Ristovski) // Set the real height of the entire chart (the one that user specified) - .style("height",height) + .style("height",height) .style("width",width) .style("background-color",jsonData.chart.style.backgroundColor) .style("font-style",jsonData.chart.style.fontStyle) @@ -725,11 +737,11 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .style("text-decoration",jsonData.subtitle.style.textDecoration) .style("font-size",jsonData.subtitle.style.fontSize) .text(jsonData.subtitle.text); - + d3.select("#main"+randomId).append("div").style("height", emptySplitDivHeight); - + d3.select("#main"+randomId).append("div").attr("id","chartD3"+randomId); - + var svg = d3.select("#chartD3"+randomId).append("div") .attr("class","chart") .style("width",width) @@ -737,22 +749,22 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .attr("align","center") .append("svg:svg") .attr("width",width) - .attr("height",heightForChartSvg) + .attr("height",heightForChartSvg) .attr("viewBox","-125 -125 "+(Number(width)+250)+" "+ (Number(heightForChartSvg)+250)) .attr( "preserveAspectRatio","xMidYMid meet") - .style("background-color",jsonData.chart.style.backgroundColor) + .style("background-color",jsonData.chart.style.backgroundColor) .append("svg:g") .attr("transform", "translate(" + width / 2 + "," + ((Number(heightForChartSvg)) / 2) + ")"); - + /** * @author: Ana Tomic (atomic ana.tomic@mht.net) */ - + var tooltip=d3.select("#chartD3"+randomId) .append("div") .attr("class","tooltip") .style("opacity","0"); - + /** * values to be applied instead of undefined if some property is not specified */ @@ -762,7 +774,7 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro var backgroundColor=jsonData.tooltip.backgroundColor?jsonData.tooltip.backgroundColor:'rgba(255, 255, 255, 0.85)'; var borderWidth=jsonData.tooltip.borderWidth?jsonData.tooltip.borderWidth: '1'; var borderRadius=jsonData.tooltip.borderRadius?jsonData.tooltip.borderRadius:'3'; - + d3.select(panel).selectAll(".tooltip") .style("position","fixed") .style("text-align",jsonData.tooltip.align) @@ -785,66 +797,66 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .style("left","50%") .style("top","50%") .style("transform","translate(-50%, -50%)"); - + /** * [START] Data processing part */ var rows = jsonData.data[0].rows; //var source,target,value; - + var matrix = new Array(rows.length); - + // for (var i = 0; i < matrix.length;i++) // { // matrix[i] = new Array(elemSize); -// } - - // use dataset as-is - for (i = 0; i < rows.length; i++) - { +// } + + // use dataset as-is + for (i = 0; i < rows.length; i++) + { matrix[i] = []; - - for (j = 0; j < rows.length; j++) + + for (j = 0; j < rows.length; j++) { - var column = 'column_'+(j+1); + var column = 'column_'+(j+1); matrix[i][j] = parseFloat(rows[i][column]); - }; - }; - + }; + }; + // Variable that will let us render this chart part, but preventing listening for the mouseover event var arcs = null; - + /** * Which column is paired with which row (row is the initial point of view) - * - array of objects that are composed of row attribute and its array of + * - array of objects that are composed of row attribute and its array of * columns that are intersected with it and have value != 0 */ - + for (var i=0; i we do not need information about intersection of this columns with the row of the same name (i,i), + * "... && rowName!=columnName" => we do not need information about intersection of this columns with the row of the same name (i,i), * since we got this information when populating the 'columnsPairedWithRows' array. We do must not duplicate the data. */ // TODO: Should I leave the rows that we already found as intersected with the actual column? Maybe for two separate tables? @@ -886,34 +898,34 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro { tempArraysObject.row = rowName; tempArraysObject.value = rows[j]["column_"+(i+1)]; - + tempArray.push(tempArraysObject); - } + } } - - tempObject.pairedWith = tempArray; - + + tempObject.pairedWith = tempArray; + rowsPairedWithColumns.push(tempObject); - } - + } + /** * Check if there are any arcs (if there is non-zero value for the item that is * selected in the Cockpit (Cockpit selection). - * + * * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ + */ if (arcs!=null) { - + // since we have all the data, enable fading of stripes and rendering the table in legend arcs - .on("mouseover", fadeMouseOver()) + .on("mouseover", fadeMouseOver()) .on("mouseout", fadeMouseOut()); - + arcs.on ( - "click", clickOnItem() - ); - + "click", clickOnItem() + ); + } } else @@ -922,86 +934,86 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * Clean the HTML body (content that was previously prepared for the CHORD chart) * and place the error information message, so use can know that chart cannot be * rendered due to bad data that user set in the Designer (chart document template). - * + * * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ cleanChart(); - - var errorInfoForChordChart = + + var errorInfoForChordChart = "" + "There is a problem with the rendering of the chart." + " " + - + "
" + "
" + - + "Please, check if data (series item and categories) are well defined. " + - + "
" + "
" + - + "" + "NOTE" + "" + ": You must provide one series item and two categories " + "that should have the same number of different elements (a perfect matrix with N rows and N columns)."; - + d3.select(panel).append("div").html(errorInfoForChordChart); } - + /** * We need sum of values on all arcs on the chart in order to provide equidistant * ticks organization and the same princip for numeric labels. * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ function sumOfAllArcs(ticks) - { + { var tempMax = 0; - + for (var i=0; i 1 || (matrix.length==1 && matrix[0][0]!=0)) @@ -1018,18 +1030,18 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro // draws circles and defines the effect on the passage mouse var arcs1 = svg.append("svg:g").selectAll("path") .data(chord.groups) - .enter(); - + .enter(); + arcs = arcs1.append("svg:path") .style("fill", function(d) { return fill(d.index); }) .style("stroke", function(d) { return fill(d.index); }) - .attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius)); + .attr("d", d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius)); var ticks1 = svg.append("svg:g").selectAll("g") .data(chord.groups) .enter(); - - + + /** * Set the value of total sum of values on all arcs to the global variable, * so we can access ot from the function that needs this information. That @@ -1037,7 +1049,7 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ totalValueOnArcs = sumOfAllArcs(ticks1); - + var ticks = ticks1.append("svg:g").selectAll("g") .data(groupTicks) .enter().append("svg:g") @@ -1045,13 +1057,13 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" + "translate(" + outerRadius + ",0)"; }); - + /** * Customization for category labels (desciptions over arcs of the CHORD chart). * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ var literalLabelsFontCustom = jsonData.xAxis.labels.style; - + ticks1.append("svg:text") .each(function(d,i) { d.angle = (d.startAngle + d.endAngle) / 2; }) .attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) @@ -1061,27 +1073,27 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro + (d.angle > Math.PI ? "rotate(180)" : ""); }) .attr("fill", literalLabelsFontCustom.color) - .style("font-family",literalLabelsFontCustom.fontFamily) + .style("font-family",literalLabelsFontCustom.fontFamily) .style("font-style",literalLabelsFontCustom.fontStyle) .style("font-size",literalLabelsFontCustom.fontSize) .style("font-weight",literalLabelsFontCustom.fontWeight) .style("text-decoration",literalLabelsFontCustom.textDecoration) - .text(function(d,i) { return allFieldsArray[i];}) + .text(function(d,i) { return allFieldsArray[i];}) - //aggiunge le lineette "graduate" + //aggiunge le lineette "graduate" ticks.append("svg:line") .attr("x1", "1") .attr("y1", "0") .attr("x2", "5") .attr("y2", "0") .style("stroke", "#FF0000"); // TODO: Customize the color of ticks ??? - + /** - * Customization for serie labels (ticks on arcs of the CHORD chart). * + * Customization for serie labels (ticks on arcs of the CHORD chart). * * @author: danristo (danilo.ristovski@mht.net) */ var tickLabelsFontCustom = jsonData.yAxis.labels.style; - + //aggiunge le label unit� di misura ticks.append("svg:text") .attr("x", "8") @@ -1089,13 +1101,13 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .attr("transform", function(d) { return d.angle > Math.PI ? "rotate(180)translate(-16)" : null; }) .style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) .attr("fill", tickLabelsFontCustom.color) - .style("font-family",tickLabelsFontCustom.fontFamily) + .style("font-family",tickLabelsFontCustom.fontFamily) .style("font-style",tickLabelsFontCustom.fontStyle) .style("font-size",tickLabelsFontCustom.fontSize) .style("font-weight",tickLabelsFontCustom.fontWeight) .style("text-decoration",tickLabelsFontCustom.textDecoration) .text(function(d) { return d.label; }); - + } else { @@ -1104,32 +1116,32 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ var literalLabelsFontCustom = jsonData.xAxis.labels.style; - + svg.append("svg:g").selectAll("g") .data(chord.groups) .enter().append("svg:text") .attr("fill", literalLabelsFontCustom.color) - .style("font-family",literalLabelsFontCustom.fontFamily) + .style("font-family",literalLabelsFontCustom.fontFamily) .style("font-style",literalLabelsFontCustom.fontStyle) .style("font-size",literalLabelsFontCustom.fontSize) .style("font-weight",literalLabelsFontCustom.fontWeight) .style("text-decoration",literalLabelsFontCustom.textDecoration) .text ( - function(d) { - + function(d) { + /** - * Return the text value of the only series zero value item that is - * selected by clicking on the arc towards which no one (no item) is + * Return the text value of the only series zero value item that is + * selected by clicking on the arc towards which no one (no item) is * coming. * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ - return allFieldsArray[0]; - + return allFieldsArray[0]; + } ); } - + //disegna le fasce da un'area ad un altra svg.append("svg:g") .attr("class", "chord") @@ -1138,12 +1150,12 @@ function renderChordChart(jsonData,panel,handleCockpitSelection,locale,handleCro .enter().append("svg:path") .attr("d", d3.svg.chord().radius(innerRadius)) .style("fill", function(d) { return fill(d.target.index); }) - .style("opacity", opacityMouseOutAndDefault) + .style("opacity", opacityMouseOutAndDefault) .style("stroke", "#000") // TODO: Customize ?? - .style("stroke-width", ".5px"); // TODO: Customize ?? - + .style("stroke-width", ".5px"); // TODO: Customize ?? + return true; - } + } else { return false; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Parallel.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Parallel.js index 111c834ad0d..c8da2e950b3 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Parallel.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Parallel.js @@ -9,7 +9,7 @@ function renderParallelChart(data,panel,handleCockpitSelection,chartEngineSettin var records = data.data[0]; var chartEngineSharedSettings = chartEngineSettings; if(records.length>0){ - + panel.innerText = ''; if (records.length>data.limit.maxNumberOfLines){ var limitcolumn = data.limit.serieFilterColumn; @@ -469,7 +469,7 @@ function renderParallelChart(data,panel,handleCockpitSelection,chartEngineSettin * chart is bigger than this value, TOOLTIP * will not be rendered). */ - var maxNumOfRecsForDispTooltip = 20; + var maxNumOfRecsForDispTooltip = data.tooltip.maxNumberOfRecords; if (records.length <= maxNumOfRecsForDispTooltip){ @@ -636,10 +636,22 @@ function renderParallelChart(data,panel,handleCockpitSelection,chartEngineSettin var emptyMsgFontSize = parseInt(data.emptymessage.style.fontSize); //var emptyMsgTotal = emptyMsgDivHeight+emptyMsgFontSize/2; var emptyMsgTotal = emptyMsgFontSize; + + var emptyMsgAlignment = null; + if(data.emptymessage.style.align == "left") { + emptyMsgAlignment = "flex-start"; + } else if (data.emptymessage.style.align == "right") { + emptyMsgAlignment = "flex-end"; + } else { + emptyMsgAlignment = "center"; + } + // Set empty message - d3.select(panel).append("div") - .style("color",data.emptymessage.style.color) - .style("text-align",data.emptymessage.style.align) + d3.select(panel) + .style("color",data.emptymessage.style.color) + .style("display","flex") + .style("align-items","center") + .style("justify-content",emptyMsgAlignment) .style("font-family",data.emptymessage.style.fontFamily) .style("font-style",data.emptymessage.style.fontStyle) .style("font-weight",data.emptymessage.style.fontWeight) diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Wordcloud.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Wordcloud.js index eca6e730626..ecd46d7e4a4 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Wordcloud.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/d3/renderD3Wordcloud.js @@ -589,6 +589,7 @@ function renderWordCloud(chartConf,panel,handleCockpitSelection,locale, handleCr layout.start(); function draw(words,e) { + panel.innerText = ''; var randomId= Math.round((Math.random())*10000); /** @@ -626,8 +627,8 @@ function renderWordCloud(chartConf,panel,handleCockpitSelection,locale, handleCr .append("div").attr("id","main"+randomId) .attr("class","d3-container") .style("margin","auto") // Center chart horizontally (Danilo Ristovski) - .style("height",heightNormalized) - .style("width",widthNormalized-widthCorrection) + .style("height",heightNormalized-10) + .style("width",widthNormalized-widthCorrection-10) .style("font-family", chartConf.chart.style.fontFamily) .style("font-style", chartConf.chart.style.fontStyle) .style("font-weight", chartConf.chart.style.fontWeight) @@ -661,13 +662,21 @@ function renderWordCloud(chartConf,panel,handleCockpitSelection,locale, handleCr emptyMsgTextDecoration = (chartConf.emptymessage.style.textDecoration == "underline" || chartConf.chart.style.textDecoration == "underline") ? "underline" : "none"; - // Set title - d3.select("#main"+randomId).append("div") - .style("height",emptyMsgTotal) - .style("position",chartConf.emptymessage.position) - .style("left",chartConf.emptymessage.paddingLeft) + var emptyMsgAlignment = null; + if(chartConf.emptymessage.style.align == "left") { + emptyMsgAlignment = "flex-start"; + } else if (chartConf.emptymessage.style.align == "right") { + emptyMsgAlignment = "flex-end"; + } else { + emptyMsgAlignment = "center"; + } + + // Set empty message + d3.select(panel) + .style("display","flex") + .style("align-items","center") + .style("justify-content",emptyMsgAlignment) .style("color",chartConf.emptymessage.style.color) - .style("text-align",chartConf.emptymessage.style.align) .style("font-family",chartConf.emptymessage.style.fontFamily) .style("font-style", emptyMsgFontStyle) .style("font-weight", emptyMsgFontWeight) @@ -746,8 +755,8 @@ function renderWordCloud(chartConf,panel,handleCockpitSelection,locale, handleCr var bacground=d3.select("#main"+randomId) .append("div").attr("id","chart"+randomId).attr("class","d3chartclass") .append("svg") - .attr("width", widthNormalized-widthCorrection) - .attr("height", heightNormalized-(Number(removePixelsFromFontSize(chartConf.title.style.fontSize)) + .attr("width", widthNormalized-widthCorrection-10) + .attr("height", heightNormalized-10-(Number(removePixelsFromFontSize(chartConf.title.style.fontSize)) +Number(removePixelsFromFontSize(chartConf.subtitle.style.fontSize)))*1.6); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/chartDesigner.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/chartDesigner.js index d6b33c6cd02..909c428a339 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/chartDesigner.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/chartDesigner.js @@ -36,14 +36,15 @@ app.directive("chartDesigner" ,function(chartDesignerBasePath){ } }); -function chartDesignerFunction($scope, sbiModule_translate,channelMessaging,sbiModule_util,$scope,sbiModule_config, sbiModule_restServices, cockpitModule_widgetServices,sbiModule_messaging,sbiModule_logger,$mdToast,$mdDialog,sbiModule_user,$httpParamSerializer) { +function chartDesignerFunction($scope, sbiModule_translate,channelMessaging,sbiModule_util,$scope,sbiModule_config, sbiModule_restServices,StructureTabService, ChartDesignerData,cockpitModule_widgetServices,sbiModule_messaging,sbiModule_logger,$mdToast,$mdDialog,sbiModule_user,$httpParamSerializer) { $scope.translate = sbiModule_translate; $scope.httpParamSerializer = $httpParamSerializer; $scope.selectedChartType = ""; $scope.selectedTab = {'tab' : 0}; var urlForDataset=""; $scope.enterpriseEdition = sbiModule_user.functionalities.indexOf("SeeAdvancedTab")>-1; - + StructureTabService.enterpriseEdition = $scope.enterpriseEdition; + ChartDesignerData.enterpriseEdition = $scope.enterpriseEdition; if($scope.isCockpitEng){ urlForDataset = "../api/1.0/chart/jsonChartTemplate/usedDataset/"+$scope.datasetId; }else{ @@ -152,7 +153,10 @@ function chartDesignerFunction($scope, sbiModule_translate,channelMessaging,sbiM }) $scope.$on('updateMeasuresWithCF', function(event,data) { - $scope.getMetadata(); + $scope.getMetadata();if ($scope.getMetadata){ + $scope.numberOfSeriesContainers = 0; + $scope.getMetadata(); + } }) $scope.refreshJsonTree = function() { @@ -214,26 +218,24 @@ function chartDesignerFunction($scope, sbiModule_translate,channelMessaging,sbiM groupby:"", groupbyNames:"", name:"", - orderColumn:"", - orderType:"", }; + if(chartType.toUpperCase()!='BAR' && chartType.toUpperCase()!='LINE') { + $scope.chartTemplate.VALUES.CATEGORY.orderColumn=""; + $scope.chartTemplate.VALUES.CATEGORY.orderType=""; + } for (var i = 0; i < $scope.categories.length; i++) { if(i==0){ $scope.chartTemplate.VALUES.CATEGORY.column = $scope.categories[i].column; $scope.chartTemplate.VALUES.CATEGORY.name = $scope.categories[i].name; if($scope.chartTemplate.VALUES.CATEGORY.orderColumn==""){ - if(tempDrillOrder && chartType.toUpperCase() !="PIE" && chartType.toUpperCase() !="RADAR"){ - $scope.chartTemplate.VALUES.CATEGORY.orderColumn = tempDrillOrder[$scope.categories[i].column] ? tempDrillOrder[$scope.categories[i].column].orderColumn : $scope.categories[i].orderColumn; - } else { + if(!(tempDrillOrder && chartType.toUpperCase() !="PIE" && chartType.toUpperCase() !="RADAR")){ $scope.chartTemplate.VALUES.CATEGORY.orderColumn = $scope.categories[i].orderColumn; } } if($scope.chartTemplate.VALUES.CATEGORY.orderType==""){ - if(tempDrillOrder && chartType.toUpperCase() !="PIE" && chartType.toUpperCase() !="RADAR"){ - $scope.chartTemplate.VALUES.CATEGORY.orderType = tempDrillOrder[$scope.categories[i].column] ? tempDrillOrder[$scope.categories[i].column].orderType : $scope.categories[i].orderType; - } else { + if(!(tempDrillOrder && chartType.toUpperCase() !="PIE" && chartType.toUpperCase() !="RADAR")){ $scope.chartTemplate.VALUES.CATEGORY.orderType = $scope.categories[i].orderType; } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/chart-tab/chart-tab.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/chart-tab/chart-tab.js index 64f1b0913ca..0bfeaac00a6 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/chart-tab/chart-tab.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/chart-tab/chart-tab.js @@ -161,7 +161,7 @@ function chartTabControllerFunction($scope,$timeout,sbiModule_translate,sbiModul $scope.localMod.chartTemplate = $scope.chartTemplate; $scope.selectedChartType = $scope.chartTemplate.type.toLowerCase(); - chartBackwardCompatibilityService.updateTemplate($scope.chartTemplate); + chartBackwardCompatibilityService.updateTemplate($scope.chartTemplate,$scope.enterpriseEdition); setConfigurationButtons($scope.chartTemplate.type.toLowerCase()); } else { diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/configuration-tab.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/configuration-tab.html index e9910463e58..ba364d4de6c 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/configuration-tab.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/configuration-tab.html @@ -45,7 +45,7 @@

-
+
@@ -53,7 +53,7 @@

-
+
@@ -61,7 +61,7 @@

-
+
@@ -69,7 +69,7 @@

-
+
@@ -77,7 +77,7 @@

-
+
@@ -85,7 +85,7 @@

-
+
@@ -93,7 +93,7 @@

-
+
@@ -101,7 +101,7 @@

-
+
@@ -109,7 +109,7 @@

-
+
@@ -117,7 +117,7 @@

-
+
@@ -125,7 +125,7 @@

-
+
@@ -133,7 +133,7 @@

-
+
@@ -141,7 +141,7 @@

-
+
@@ -149,7 +149,7 @@

-
+
@@ -157,7 +157,7 @@

-
+
@@ -165,13 +165,13 @@

-
+
-
+
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/explanation.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/explanation.html index 5b144227061..5716a6450a2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/explanation.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/explanation.html @@ -2,8 +2,7 @@ - {{option.name}} @@ -16,15 +15,13 @@ - {{option.name}} - {{option.name}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/generic_details.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/generic_details.html index ded17ed12ab..ea913a0ad02 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/generic_details.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/generic_details.html @@ -67,13 +67,13 @@
- + - + - {{option.name}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/tooltip.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/tooltip.html index a286561e6fa..fcf85aaae80 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/tooltip.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/configuration-tab/tooltip.html @@ -31,15 +31,13 @@ - {{option.name}} - {{option.name}} @@ -48,14 +46,21 @@ + ng-min="0" /> + ng-min="0" /> + + + +
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/axis_configuration_details.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/axis_configuration_details.html index 4cfa5b0e91d..8bf09515793 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/axis_configuration_details.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/axis_configuration_details.html @@ -10,13 +10,6 @@
-
- - - - -
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_DateTime.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_DateTime.html index e96a173e23f..098f76d9089 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_DateTime.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_DateTime.html @@ -21,14 +21,14 @@ - + {{translate.load("sbi.chartengine.structure.categoryStyleConfig.categoryDate.info")}}
-
+
-
+
- {{option.name}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_axis_configuration_details.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_axis_configuration_details.html index c8b5e794b12..deaf0d6df38 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_axis_configuration_details.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/categories_axis_configuration_details.html @@ -5,14 +5,6 @@ Categories container alias: {{axisForDisplay.alias}} -
- - - - -
-
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.html index ca7fd56ec6d..47f24423283 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.html @@ -43,7 +43,7 @@

- {{measure.alias || measure.id}} + {{measure.alias || measure.id}} ({{measure.aggregationSelected}}) @@ -51,7 +51,7 @@

- {{measure.alias || measure.id}} + {{measure.alias || measure.id}} ({{measure.aggregationSelected}}) @@ -180,7 +180,7 @@

+ disableHtmlElementForChartJs() && selectedChartType.toLowerCase()!='scatter'"> Datetime and grouping @@ -456,7 +456,7 @@

- {{seriesItem}} + {{seriesItem}} ({{getAggregationFunction(seriesItem)}}) diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.js index a7961d7a5b5..7bb10deaf93 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/chartstructure-tab.js @@ -51,7 +51,11 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res },true) $scope.$watch('chartTemplate.dateTime',function(newValue,oldValue){ - if(!newValue && $scope.chartTemplate) $scope.chartTemplate.categoryDate = ""; + if($scope.chartTemplate && newValue!=oldValue){ + if(newValue==false) $scope.chartTemplate.CHART ? $scope.chartTemplate.CHART.categoryDate = "" : $scope.chartTemplate.categoryDate = "" ; + else $scope.chartTemplate.CHART ? $scope.chartTemplate.CHART.categoryDate = $scope.categories[0].column : $scope.chartTemplate.categoryDate = $scope.categories[0].column;; + } + },true) $scope.$watch('categories[0].orderColumn',function(newValue, oldValue){ @@ -292,6 +296,13 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res } + $scope.getAggregationFunction = function(serieName) { + for (i=0; i<$scope.chartTemplate.VALUES.SERIE.length; i++) { + if ($scope.chartTemplate.VALUES.SERIE[i].column == serieName) { + return $scope.chartTemplate.VALUES.SERIE[i].groupingFunction; + } + } + } // Called when the user clicks on the measure in its container, so the measure can be used as a series item in the chart. $scope.moveMeasureToSeries = function(item,seriesContainer) { @@ -787,6 +798,10 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res $scope.seriesItemRemove = function(seriesItem,seriesContainerName) { + if($scope.chartTemplate.groupedSerie!=undefined && $scope.chartTemplate.groupedSerie == seriesItem){ + delete $scope.chartTemplate.groupedSerie; + } + if($scope.chartTemplate.VALUES.SERIE.length != undefined && $scope.chartTemplate.VALUES.SERIE.constructor == Array){ for (var i = 0; i < $scope.chartTemplate.VALUES.SERIE.length; i++) { if($scope.chartTemplate.VALUES.SERIE[i].column == seriesItem && $scope.chartTemplate.VALUES.SERIE[i].axis == seriesContainerName){ @@ -883,14 +898,14 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -918,11 +933,11 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res } $scope.clearAxisMajorGridDetails = function () { - $scope.axisForDisplay.MAJORGRID = {"interval": "","style": {"typeLine": "","color": ""}} + $scope.axisForDisplay.MAJORGRID = {"interval": "","style": {"typeline": "","color": ""}} } $scope.clearAxisMinorGridDetails = function () { - $scope.axisForDisplay.MINORGRID = {"interval": "","style": {"typeLine": "","color": ""}} + $scope.axisForDisplay.MINORGRID = {"interval": "","style": {"typeline": "","color": ""}} } $scope.removeSeriesContainer = function(seriesContainer) { @@ -990,7 +1005,8 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res // TODO: Check if these chart types are the only one that for which we should exclude the Ordering column option in the categories drop-down menu $scope.categoriesContainerConfigDropDownExcludeTypes = ["wordcloud","treemap","parallel"]; - $scope.categoriesOrderColumnExcludeTypes = ["parallel","chord"]; + $scope.categoriesOrderColumnExcludeTypes = ["parallel","chord","bubble"]; + $scope.seriesOrderColumnExcludeTypes = ['chord', 'heatmap', 'treemap', 'parallel', 'sunburst', 'wordcloud', 'bubble']; $scope.categoriesConfigExcludeTypes = ["pie","sunburst", "bubble"]; $scope.categoriesTitleConfigExcludeTypes = ["parallel","pie","sunburst","chord", "bubble"]; $scope.categoriesDateTimeIncludedTypes = ["bar","line","radar","scatter"]; @@ -1054,4 +1070,24 @@ function structureTabControllerFunction($scope,sbiModule_translate,sbiModule_res $scope.getMetadata(); $scope.checkCategories(); + $scope.getFilteredSeries = function(){ + + var filteredSeries = []; + for(var i = 0; i < $scope.chartTemplate.VALUES.SERIE.length; i++) { + + var indexSeriesContainer_X = sbiModule_util.findInArray($scope.seriesContainers,'name',"X"); + var indexSeriesContainer_Z = sbiModule_util.findInArray($scope.seriesContainers,'name',"Z"); + + if(indexSeriesContainer_X>-1){ + var indexSeries_X = $scope.seriesContainers[indexSeriesContainer_X].series.indexOf($scope.chartTemplate.VALUES.SERIE[i].column); + } + if(indexSeriesContainer_Z>-1){ + var indexSeries_Z = $scope.seriesContainers[indexSeriesContainer_Z].series.indexOf($scope.chartTemplate.VALUES.SERIE[i].column); + } + + if(indexSeries_X==-1 && indexSeries_Z==-1) filteredSeries.push($scope.chartTemplate.VALUES.SERIE[i]) + } + return filteredSeries + } + } \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/ordering_column.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/ordering_column.html index 0d449ca8de5..168e3486d99 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/ordering_column.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/ordering_column.html @@ -30,7 +30,7 @@ -
+
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/series_item_config_details.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/series_item_config_details.html index 72644b497aa..3154d603470 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/series_item_config_details.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/series_item_config_details.html @@ -15,23 +15,13 @@
- -
- - - - - {{option.name}} - - -
+ ng-if="(selectedChartType =='bar' || selectedChartType =='line' || (selectedChartType =='radar' && !chartTemplate.groupSeriesCateg)) && disableHtmlElementForChartJs()"> @@ -41,10 +31,10 @@
+ ng-if="selectedChartType =='radar' && chartTemplate.groupSeriesCateg && disableHtmlElementForChartJs()"> - +
@@ -53,8 +43,7 @@ in ascending order for this series item if this type of ordering is set and vice versa. -->
+ng-if="seriesOrderColumnExcludeTypes.indexOf(selectedChartType.toLowerCase())<0 && selectedChartType != 'gauge'"> @@ -112,22 +101,6 @@
- -
- - - - {{option.name}} - - -
-
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/splitBubble.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/splitBubble.html index 3b255fef75d..35c56f9356c 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/splitBubble.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/directives/custom_directives/structure-tab/splitBubble.html @@ -37,7 +37,7 @@

- {{seriesItem.column}} + {{seriesItem.column}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/barBackwardCompatibility/barBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/barBackwardCompatibility/barBackwardCompatibility.js new file mode 100644 index 00000000000..34332620130 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/barBackwardCompatibility/barBackwardCompatibility.js @@ -0,0 +1,47 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("barBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase()=='bar'){ + if(!chartTemplate.VALUES.CATEGORY.drillOrder){ + if(chartTemplate.VALUES.CATEGORY.orderColumn!=''){ + chartTemplate.VALUES.CATEGORY.drillOrder = {}; + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column] = {} + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column].orderColumn = chartTemplate.VALUES.CATEGORY.orderColumn; + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column].orderType = chartTemplate.VALUES.CATEGORY.orderType; + } + + } else { + delete chartTemplate.VALUES.CATEGORY.orderColumn; + delete chartTemplate.VALUES.CATEGORY.orderType; + } + } + + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/chartBackwardCompatibility/chartBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/chartBackwardCompatibility/chartBackwardCompatibility.js index 9d8f81c2654..6e2a710d6f0 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/chartBackwardCompatibility/chartBackwardCompatibility.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/chartBackwardCompatibility/chartBackwardCompatibility.js @@ -22,18 +22,24 @@ along with this program. If not, see . var chartBackwardCompatibilityServices = [] chartBackwardCompatibilityServices.push($injector.get('gaugeBackwardCompatibilityService')); chartBackwardCompatibilityServices.push($injector.get('scatterBackwardCompatibilityService')); - - - var updateTemplate = function(chartTemplate){ + chartBackwardCompatibilityServices.push($injector.get('sunburstBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('parallelBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('treemapBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('heatmapBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('barBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('lineBackwardCompatibilityService')); + chartBackwardCompatibilityServices.push($injector.get('radarBackwardCompatibilityService')); + + var updateTemplate = function(chartTemplate,enterpriseEdition){ for(var i in chartBackwardCompatibilityServices){ chartTemplate = chartBackwardCompatibilityServices[i].updateTemplate.apply(null,arguments) } return chartTemplate; } - return { - updateTemplate:updateTemplate + updateTemplate:updateTemplate, + } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/gaugeBackwardCompatibility/gaugeBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/gaugeBackwardCompatibility/gaugeBackwardCompatibility.js index c0d69219909..b50b485c7e2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/gaugeBackwardCompatibility/gaugeBackwardCompatibility.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/gaugeBackwardCompatibility/gaugeBackwardCompatibility.js @@ -21,9 +21,29 @@ along with this program. If not, see . .service("gaugeBackwardCompatibilityService", function (){ var updateTemplate = function(chartTemplate){ - if(chartTemplate.type.toLowerCase()=='gauge' && !chartTemplate.AXES_LIST.AXIS[0].TARGET){ - chartTemplate.AXES_LIST.AXIS[0].TARGET = [{"color": "","dashStyle": "Solid","value":0,"width":2}] + if(chartTemplate.type.toLowerCase()=='gauge'){ + //adding new + if(!chartTemplate.AXES_LIST.AXIS[0].TARGET){ + chartTemplate.AXES_LIST.AXIS[0].TARGET = [{"color": "","dashStyle": "Solid","value":0,"width":2}] + } + if(!chartTemplate.TOOLTIP){ + chartTemplate.TOOLTIP = {"borderWidth": 0,"borderRadius":0} + } + if(chartTemplate.VALUES.SERIE[0].TOOLTIP){ + delete chartTemplate.VALUES.SERIE[0].TOOLTIP.borderWidth; + delete chartTemplate.VALUES.SERIE[0].TOOLTIP.borderRadius; + chartTemplate.VALUES.SERIE[0].TOOLTIP = { + backgroundColor: "#D6D6D6", + style: {align: "", color: "", fontFamily: "", fontWeight: "", fontSize: ""}, + align: "", + color: "", + fontFamily: "", + fontSize: "", + fontWeight: "", + } + } } + return chartTemplate; }; return { diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/heatmapBackwardCompatibility/heatmapBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/heatmapBackwardCompatibility/heatmapBackwardCompatibility.js new file mode 100644 index 00000000000..1df1fe3d423 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/heatmapBackwardCompatibility/heatmapBackwardCompatibility.js @@ -0,0 +1,41 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("heatmapBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase()=='heatmap'){ + if(chartTemplate.TOOLTIP) { + chartTemplate.TOOLTIP.borderWidth= 0; + chartTemplate.TOOLTIP.borderRadius= 0; + } + if(chartTemplate.VALUES.SERIE[0].TOOLTIP) { + delete chartTemplate.VALUES.SERIE[0].TOOLTIP + } + } + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/lineBackwardCompatibility/lineBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/lineBackwardCompatibility/lineBackwardCompatibility.js new file mode 100644 index 00000000000..d1444df7678 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/lineBackwardCompatibility/lineBackwardCompatibility.js @@ -0,0 +1,47 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("lineBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase()=='line'){ + if(!chartTemplate.VALUES.CATEGORY.drillOrder){ + if(chartTemplate.VALUES.CATEGORY.orderColumn!=''){ + chartTemplate.VALUES.CATEGORY.drillOrder = {}; + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column] = {} + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column].orderColumn = chartTemplate.VALUES.CATEGORY.orderColumn; + chartTemplate.VALUES.CATEGORY.drillOrder[chartTemplate.VALUES.CATEGORY.column].orderType = chartTemplate.VALUES.CATEGORY.orderType; + } + + } else { + delete chartTemplate.VALUES.CATEGORY.orderColumn; + delete chartTemplate.VALUES.CATEGORY.orderType; + } + } + + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/parallelBackwardCompatibility/parallelBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/parallelBackwardCompatibility/parallelBackwardCompatibility.js new file mode 100644 index 00000000000..987d94cb33f --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/parallelBackwardCompatibility/parallelBackwardCompatibility.js @@ -0,0 +1,42 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("parallelBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase() == 'parallel'){ + if(chartTemplate.PARALLEL_TOOLTIP) { + chartTemplate.PARALLEL_TOOLTIP.maxNumberOfRecords = 50 + } + + for(serie in chartTemplate.VALUES.SERIE){ + delete chartTemplate.VALUES.SERIE[serie].scaleFactor + } + } + + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/radarBackwardCompatibility/radarBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/radarBackwardCompatibility/radarBackwardCompatibility.js new file mode 100644 index 00000000000..1498f84c340 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/radarBackwardCompatibility/radarBackwardCompatibility.js @@ -0,0 +1,39 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("radarBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase() == 'radar'){ + if(chartTemplate.VALUES.SERIE[0].serieTypeRadar!= undefined && chartTemplate.VALUES.SERIE[0].type==""){ + chartTemplate.VALUES.SERIE[0].type = chartTemplate.VALUES.SERIE[0].serieTypeRadar; + } + delete chartTemplate.VALUES.SERIE[0].serieTypeRadar; + } + + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/scatterBackwardCompatibility/scatterBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/scatterBackwardCompatibility/scatterBackwardCompatibility.js index 9ea2db7f78d..f0c733ca3ac 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/scatterBackwardCompatibility/scatterBackwardCompatibility.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/scatterBackwardCompatibility/scatterBackwardCompatibility.js @@ -21,8 +21,10 @@ along with this program. If not, see . .service("scatterBackwardCompatibilityService", function (){ var updateTemplate = function(chartTemplate){ - if(chartTemplate.type.toLowerCase() == 'scatter' && !chartTemplate.VALUES.SERIE[0].TOOLTIP.tooltipExpression){ - chartTemplate.VALUES.SERIE[0].TOOLTIP.tooltipExpression = "" + if(chartTemplate.type.toLowerCase() == 'scatter'){ + if(!chartTemplate.VALUES.SERIE[0].TOOLTIP.tooltipExpression){ + chartTemplate.VALUES.SERIE[0].TOOLTIP.tooltipExpression = "" + } } return chartTemplate; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/sunburstBackwardCompatibility/sunburstBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/sunburstBackwardCompatibility/sunburstBackwardCompatibility.js new file mode 100644 index 00000000000..0307f355aee --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/sunburstBackwardCompatibility/sunburstBackwardCompatibility.js @@ -0,0 +1,56 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("sunburstBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate,enterpriseEdition){ + if(chartTemplate.type.toLowerCase()=='sunburst'){ + if(enterpriseEdition) { + delete chartTemplate.TOOLBAR; + delete chartTemplate.opacMouseOver; + delete chartTemplate.percAbsolSliceValue; + if(!chartTemplate.TOOLTIP) { + chartTemplate.TOOLTIP = {}; + chartTemplate.TOOLTIP.borderWidth= 0; + chartTemplate.TOOLTIP.borderRadius= 0; + } + if(!chartTemplate.VALUES.SERIE[0].TOOLTIP) { + chartTemplate.VALUES.SERIE[0].TOOLTIP = { + "backgroundColor":"#D6D6D6", + "style":{ + "align":"", + "color":"", + "fontFamily":"", + "fontSize":"", + "fontWeight":"" + } + } + } + } + } + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/treemapBackwardCompatibility/treemapBackwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/treemapBackwardCompatibility/treemapBackwardCompatibility.js new file mode 100644 index 00000000000..c0974faf95b --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/backward/treemapBackwardCompatibility/treemapBackwardCompatibility.js @@ -0,0 +1,37 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module("chartBackwardCompatibilityModule") + + .service("treemapBackwardCompatibilityService", function (){ + + var updateTemplate = function(chartTemplate){ + if(chartTemplate.type.toLowerCase()=='treemap'){ + if(!chartTemplate.TOOLTIP) { + chartTemplate.TOOLTIP = {"borderWidth":0, "borderRadius":0} + } + } + return chartTemplate; + }; + return { + updateTemplate:updateTemplate + } + }); + + +})(); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/chartDesignerServices.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/chartDesignerServices.js index 7a9b60259df..92e2be22f10 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/chartDesignerServices.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/designer/services/chartDesignerServices.js @@ -19,7 +19,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) .service('ChartDesignerData',function(sbiModule_restServices, sbiModule_messaging,sbiModule_translate,sbiModule_config, $http,chartDesignerBasePath){ - + this.enterpriseEdition = false; this.getFontSizeOptions = function(){ var data = [ {name:"",value:""}, @@ -183,9 +183,9 @@ angular.module('ChartDesignerService', ['chartRendererModule']) case 'sunburst': var options =[ {name:sbiModule_translate.load("sbi.chartengine.designer.tab.configuration.palette"),value:"palette"}, - {name:sbiModule_translate.load("sbi.chartengine.designer.tab.configuration.sequence"),value:"sequence"}, {name:sbiModule_translate.load("sbi.chartengine.designer.tab.configuration.exlpanation"),value:"explanation"} ] + if(!this.enterpriseEdition) options.push({name:sbiModule_translate.load("sbi.chartengine.designer.tab.configuration.sequence"),value:"sequence"}) Array.prototype.push.apply(data, options); return data; break; @@ -303,8 +303,8 @@ angular.module('ChartDesignerService', ['chartRendererModule']) */ .service("StructureTabService", function(sbiModule_restServices,sbiModule_messaging,sbiModule_translate,sbiModule_config,chartDesignerBasePath){ - var translate = sbiModule_translate; - + var translate = sbiModule_translate; + this.enterpriseEdition = false; this.getBaseTemplate = function(type) { var barLine = { "CHART":{ @@ -320,14 +320,12 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "TOOLTIP":{ "borderWidth":0, - "borderRadius":0, + "borderRadius":0 }, "VALUES":{ "CATEGORY":{ "name":"", "column":"", - "orderColumn":"", - "orderType":"", "groupby":"", "groupbyNames":"" }, @@ -358,7 +356,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, }, "TOOLTIP":{ - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "showAbsValueTooltip":false, "showPercentageTooltip":true, "style":{ @@ -392,20 +390,20 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "fontWeight":"" }, "labels":{ - "precision":2, + "precision":0, "scaleFactor": "empty", }, "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -416,8 +414,55 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "COLORPALETTE":{ "COLOR":[ - - ] + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height":100, @@ -428,7 +473,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "SUBTITLE":{ @@ -456,8 +501,8 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "LEGEND":{ "layout":"", - "position":"top", - "show":false, + "position":"bottom", + "show":true, "showCheckboxes":true, "style":{ "align":"", @@ -504,14 +549,18 @@ angular.module('ChartDesignerService', ['chartRendererModule']) } } - var chartType = type.toUpperCase(); + var chartType = type.toUpperCase(); - var tempPlots = { + if(chartType!='BAR' && chartType!='LINE') { + barLine.CHART.VALUES.CATEGORY.orderColumn=""; + barLine.CHART.VALUES.CATEGORY.orderType=""; + } + var tempPlots = { "plotBands":[{"label":{"text": "","align": "center"},"color":"","from":"","to":""}], "plotLines": [{"label":{"text": "","align": "center"},"color": "","dashStyle": "","value":"","width":0}] - } + } - var tempXAxis = { + var tempXAxis = { "plotBands":tempPlots.plotBands, "plotLines": tempPlots.plotLines, "id":"X", @@ -539,7 +588,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) } } - var axisTitle = { + var axisTitle = { "text":"", "style":{ @@ -552,11 +601,11 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }; - if(chartType == 'PIE'){ + if(chartType == 'PIE'){ barLine.CHART.AXES_LIST.AXIS[0].TITLESERIE = titleSerie; barLine.CHART.type = chartType; - }else { + }else { barLine.CHART.type = chartType; barLine.CHART.alignAxis = {"alignAxis": true}; @@ -571,7 +620,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) barLine.CHART.dateFormat = "day"; barLine.CHART.hideAxisTitleSerie = true; barLine.CHART.hideAxisTitleCategory = true; - } + } return barLine.CHART; } @@ -592,7 +641,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "TOOLTIP":{ "borderWidth":0, "borderRadius":0, - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "style":{ "align":"", "color":"", @@ -657,7 +706,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "fontWeight":"" }, "labels":{ - "precision":2, + "precision":0, "scaleFactor": "empty", }, "plotBands":[{"label":{"text": "","align": "center"},"color":"","from":"","to":""}], @@ -666,14 +715,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -691,9 +740,29 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "fontFamily":"", "fontSize":"", "fontWeight":"" - },"plotBands":[{"label":{"text": "","align": "center"},"color":"","from":"","to":""}], + }, + "min":'auto', + "max":'auto', + "MAJORGRID":{ + "interval":"", + "style":{ + "typeline":"", + "color":"" + } + }, + "MINORGRID":{ + "interval":"", + "style":{ + "typeline":"", + "color":"" + } + }, + "plotBands":[{"label":{"text": "","align": "center"},"color":"","from":"","to":""}], "plotLines": [{"label":{"text": "","align": "center"},"color": "","dashStyle": "","value":"","width":0}], - + "labels":{ + "precision":0, + "scaleFactor": "empty", + }, "TITLE":{ "text":"", "style":{ @@ -716,8 +785,55 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "COLORPALETTE":{ "COLOR":[ - - ] + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height":100, @@ -727,7 +843,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "SUBTITLE":{ @@ -755,8 +871,8 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "LEGEND":{ "layout":"", - "position":"top", - "show":false, + "position":"bottom", + "show":true, "style":{ "align":"", "color":"", @@ -809,6 +925,10 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "text": "" }, + "TOOLTIP":{ + "borderWidth":0, + "borderRadius":0 + }, "VALUES": { "SERIE": [{ "axis": "", @@ -826,7 +946,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showValue": true, "type": "", "TOOLTIP": { - "backgroundColor": "", + "backgroundColor": "#D6D6D6", "style": { "align":"", "color":"", @@ -908,7 +1028,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "heightDimType": "percentage", @@ -916,7 +1085,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "seriesStacking": false, "style":{ "fontFamily":"", - "fontSize":"", + "fontSize":"12px", "fontWeight":"", "backgroundColor":"#FFFFFF" }, @@ -991,17 +1160,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showAbsValue": false, "showPercentage": false, "showValue": true, - "type": "", - "TOOLTIP": { - "backgroundColor": "", - "style": { - "align":"", - "color":"", - "fontFamily":"", - "fontWeight":"", - "fontSize":"" - } - } + "type": "" }] }, "type": "HEATMAP", @@ -1025,14 +1184,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -1072,7 +1231,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "heightDimType": "percentage", @@ -1082,7 +1290,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "width": 100, @@ -1109,8 +1317,8 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "LEGEND": { "layout": "", - "position": "", - "show": false, + "position": "bottom", + "show": true, "style":{ "align":"", "color":"", @@ -1134,15 +1342,19 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "text": "" } }, - "TOOLTIP": { - "style":{ - "align":"", - "color":"", - "fontFamily":"", - "fontWeight":"", - "fontSize":"" - } + "TOOLTIP":{ + "borderWidth":0, + "borderRadius":0, + "backgroundColor": "#D6D6D6", + "style": { + "align":"", + "color":"", + "fontFamily":"", + "fontWeight":"", + "fontSize":"" + } } + } return heatTemp; @@ -1155,7 +1367,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "align":"", "color":"", "fontFamily":"", - "fontSize":"", + "fontSize":"12px", "fontWeight":"" }, "text":"" @@ -1184,19 +1396,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showValue":true, "showAbsValue":false, "showPercentage":false, - "scaleFactor":"empty", - "type":"", - "TOOLTIP":{ - "backgroundColor":"", - "style":{ - "rotate":"", - "align":"", - "color":"", - "fontFamily":"", - "fontSize":"", - "fontWeight":"" - }, - } + "type":"" } ] }, @@ -1224,14 +1424,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -1278,7 +1478,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) } }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "heightDimType": "percentage", @@ -1289,7 +1538,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "width": 100, @@ -1310,11 +1559,12 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "color":"", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"11px" }, "text":"" }, "LEGEND": { + "position": "bottom", "TITLE": { "style":{ "fontFamily":"Arial", @@ -1340,13 +1590,15 @@ angular.module('ChartDesignerService', ['chartRendererModule']) } }, "PARALLEL_TOOLTIP": { + "backgroundColor":"#D6D6D6", "style":{ "fontFamily":"Arial", "fontSize":"12px", "border":0, "borderRadius":0, "fontWeight":"" - } + }, + "maxNumberOfRecords":50 } } @@ -1394,7 +1646,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "scaleFactor": "empty", "type": "", "TOOLTIP":{ - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "style":{ "rotate":"", "align":"", @@ -1423,14 +1675,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -1470,7 +1722,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "isCockpitEngine": "", @@ -1478,13 +1779,13 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "width": 100, "LEGEND": { "layout": "", - "position": "", - "show": false, + "position": "bottom", + "show": true, "style":{ "align":"", "color":"", @@ -1589,7 +1890,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, }, "TOOLTIP":{ - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "style":{ "rotate":"", "align":"", @@ -1620,20 +1921,20 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "fontWeight":"" }, "labels":{ - "precision":2, + "precision":0, "scaleFactor": "empty", }, "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -1679,7 +1980,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "borderVisible": false, "height": 100, @@ -1692,7 +2042,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "width": 100, @@ -1700,8 +2050,8 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "zoomType": "", "LEGEND": { "layout": "", - "position": "", - "show": false, + "position": "bottom", + "show": true, "style":{ "align":"", "color":"", @@ -1764,6 +2114,10 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "text":"" }, + "TOOLTIP":{ + "borderWidth":0, + "borderRadius":0 + }, "VALUES": { "CATEGORY": [{ "column": "", @@ -1787,7 +2141,17 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "type": "", "showAbsValue": false, "showPercentage": false, - "scaleFactor": "empty" + "scaleFactor": "empty", + "TOOLTIP":{ + "backgroundColor":"#D6D6D6", + "style":{ + "align":"", + "color":"", + "fontFamily":"", + "fontSize":"", + "fontWeight":"" + } + }, }] }, "type": "SUNBURST", @@ -1808,14 +2172,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -1855,7 +2219,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "isCockpitEngine": "", @@ -1864,7 +2277,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "width": 100, @@ -1888,17 +2301,6 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "text": "" }, - "TOOLBAR": { - "style":{ - "position":"top", - "spacing":5, - "tail":10, - "percFontColor":"#000000", - "fontFamily":"", - "fontWeight":"normal", - "fontSize":"12px", - } - }, "EMPTYMESSAGE":{ "style":{ "align":"", @@ -1926,7 +2328,19 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "seriesStacking": false, "percAbsolSliceValue": "" }; - + if(!this.enterpriseEdition){ + sunburstTemp.TOOLBAR = { + "style":{ + "position":"top", + "spacing":5, + "tail":10, + "percFontColor":"#000000", + "fontFamily":"", + "fontWeight":"normal", + "fontSize":"12px", + } + } + } return sunburstTemp; } @@ -1942,6 +2356,10 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "text":"" }, + "TOOLTIP":{ + "borderWidth":0, + "borderRadius":0 + }, "VALUES": { "CATEGORY": [{ "column": "", @@ -1964,7 +2382,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showValue": "", "type": "", "TOOLTIP":{ - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "style":{ "rotate":"", "align":"", @@ -1996,14 +2414,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -2043,7 +2461,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "isCockpitEngine": "", @@ -2051,7 +2518,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "width": 100, "SUBTITLE":{ @@ -2090,7 +2557,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "align":"", "color":"", "fontFamily":"", - "fontSize":"", + "fontSize":"12px", "fontWeight":"" }, "text":"" @@ -2120,7 +2587,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showValue": true, "type": "", "TOOLTIP": { - "backgroundColor": "", + "backgroundColor": "#D6D6D6", "borderRadius": 0, "borderWidth": 0, "style":{ @@ -2151,14 +2618,14 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "MAJORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, "MINORGRID":{ "interval":"", "style":{ - "typeLine":"", + "typeline":"", "color":"" } }, @@ -2198,7 +2665,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }] }, "COLORPALETTE": { - "COLOR": [] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "height": 100, "heightDimType": "percentage", @@ -2215,7 +2731,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "backgroundColor":"#FFFFFF", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"12px" }, "styleName": "default", "width": 100, @@ -2228,7 +2744,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "color":"", "fontFamily":"", "fontWeight":"", - "fontSize":"" + "fontSize":"11px" }, "text":"" }, @@ -2257,7 +2773,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "isCockpitEngine": "", "style": { "fontFamily": "", - "fontSize": "", + "fontSize": "12px", "fontWeight": "", "backgroundColor": "#FFFFFF" }, @@ -2272,7 +2788,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "color": "", "fontFamily": "", "fontWeight": "", - "fontSize": "" + "fontSize": "12px" }, "text": "" }, @@ -2297,7 +2813,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "showValue":true, "type":"", "TOOLTIP":{ - "backgroundColor":"", + "backgroundColor":"#D6D6D6", "borderRadius":0, "borderWidth":0, "style": { @@ -2379,9 +2895,56 @@ angular.module('ChartDesignerService', ['chartRendererModule']) } }, "COLORPALETTE": { - "COLOR": [ - - ] + "COLOR":[ + {"gradient":"", + "name":"042d57", + "order":"1", + "value":"#042d57"}, + {"gradient":"", + "name":"0753a0", + "order":"2", + "value":"#0753a0"}, + {"gradient":"", + "name":"0a79e9", + "order":"3", + "value":"#0a79e9"}, + {"gradient":"", + "name":"489ff7", + "order":"4", + "value":"#489ff7"}, + {"gradient":"", + "name":"91c5fa", + "order":"5", + "value":"#91c5fa"}, + {"gradient":"", + "name":"79859b", + "order":"6", + "value":"#79859b"}, + {"gradient":"", + "name":"a5adbc", + "order":"7", + "value":"#a5adbc"}, + {"gradient":"", + "name":"d1d5dd", + "order":"8", + "value":"#d1d5dd"}, + {"gradient":"", + "name":"3b0218", + "order":"9", + "value":"#3b0218"}, + {"gradient":"", + "name":"850536", + "order":"10", + "value":"#850536"}, + {"gradient":"", + "name":"cf0854", + "order":"11", + "value":"#cf0854"}, + {"gradient":"", + "name":"f8468a", + "order":"12", + "value":"#f8468a"}, + ] }, "SUBTITLE": { "style": { @@ -2389,7 +2952,7 @@ angular.module('ChartDesignerService', ['chartRendererModule']) "color": "", "fontFamily": "", "fontWeight": "", - "fontSize": "" + "fontSize": "11px" }, "text": "" }, @@ -2403,11 +2966,6 @@ angular.module('ChartDesignerService', ['chartRendererModule']) }, "text":"" }, - "TOOLTIP": { - "style": { - "color": "" - } - }, "TOOLBAR": { "style": { "percFontColor": "" diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/heatmap/heatmap.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/heatmap/heatmap.js new file mode 100644 index 00000000000..63b440912ca --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/heatmap/heatmap.js @@ -0,0 +1,807 @@ + +function renderHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo, exportWebApp,advanced,chartConfMergeService ) { + + chartConfig = prepareChartConfForHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo, exportWebApp); + + chartConfMergeService.addProperty(advanced,chartConf); + + if (exportWebApp){ + return chartConfig; + } + var chart = new Highcharts.Chart(chartConfig); + + return chart; +// var getCrossParams= function(point){ +// var params={ +// point:{ +// name: null, // category name +// value: null, // category value +// crossNavigationDocumentName:null, +// crossNavigationDocumentParams:null, +// +// series:{ // serie name and value +// name:null, +// value: null +// }, +// group:{ // grouping category name and value +// name:null, +// value: null +// } +// } +// }; +// +// params.point.crossNavigationDocumentName=chartConf.crossNavigation.crossNavigationDocumentName; +// params.point.crossNavigationDocumentParams=chartConf.crossNavigation.crossNavigationDocumentParams; +// params.point.name=chartConf.additionalData.columns[0].value; +// params.point.value= new Date(point.x); +// params.point.series.name=chartConf.additionalData.serie.value; +// params.point.series.value=point.value; +// params.point.group.name=chartConf.additionalData.columns[1].value; +// params.point.group.value=point.label; +// +// return params; +// }; +} + + +function getCrossParamsForHeatmap(point,chartConf){ + var params={ + point:{ + name: null, // category name + value: null, // category value + y:null, + crossNavigationDocumentName:null, + crossNavigationDocumentParams:null, + + series:{ // serie name and value + name:null, + y: null + }, + group:{ // grouping category name and value + name:null, + value: null + } + } + }; + + + + params.point.category=chartConf.additionalData.columns[0].value; + if(chartConf.chart.xAxisDate){ + params.point.name= point.original; + }else{ + params.point.name= chartConf.additionalData.firstCategory[point.x]; + } + params.point.series.name=chartConf.additionalData.serie.value; + params.point.y=point.value; + params.point.group.name=chartConf.additionalData.columns[1].value; + params.point.group.value=point.label; + + return params; + +} + + +function getSelectionParammsForHeatmap(point,chartConf){ + var params={ + point:{ + name: null, // category name + value: null, // category value + } + }; + params.point.name=point.label; + params.point.value=point.value; + + return params; +} + + +function prepareChartConfForHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo,exportWebApp) { + + var start; + var startDate; + var endDate; + if(chartConf.chart.xAxisDate){ + startDate= new Date(chartConf.additionalData.firstCategory[0]); + endDate= new Date(chartConf.additionalData.firstCategory[1]); + } + var points=[]; + var data=chartConf.data[0]; + if(chartConf.chart.dateTime){ + for( i=0;i0 ? data[0][chartConf.additionalData.serie.value] : 0; + var maxValue=data.length >0 ? data[0][chartConf.additionalData.serie.value] :0; + + //ordering yaxis starts + if(chartConf.additionalData.differentOrdering==true && chartConf.additionalData.storeresultOrder){ + var map = {}; + for( i=0;i maxValue){ + maxValue=data[i][chartConf.additionalData.serie.value]; + } + + var xValue; + var xValueOriginal; + if(chartConf.chart.xAxisDate){ + xValue=data[i][chartConf.chart.datecolumn]; + + xValueOriginal =data[i][chartConf.additionalData.columns[0].value]; + }else{ + xValue=chartConf.additionalData.firstCategory.indexOf(data[i][chartConf.additionalData.columns[0].value]); + } + var point={ + "x":xValue, + "original":xValueOriginal, + //"y":chartConf.additionalData.storeresult.indexOf(data[i][chartConf.additionalData.columns[1].value]), + "value":data[i][chartConf.additionalData.serie.value], + "label":data[i][chartConf.additionalData.columns[1].value] + }; + + if(chartConf.additionalData.differentOrdering && chartConf.additionalData.storeresultOrder){ + point.y = chartConf.additionalData.storeresultOrder.indexOf(map[data[i][chartConf.additionalData.columns[1].value]]) + } else { + point.y = chartConf.additionalData.storeresult.indexOf(data[i][chartConf.additionalData.columns[1].value]) + } + + points.push(point); + } + + var colors=chartConf.colors; + var colorStops=[]; + + /** + * Provide the ending color for the color interval of the HEATMAP + * if there is one for that. Otherwise, skip this snippet. + * + * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) + */ + if (colors.length) + { + /** + * Check if user specified only 1 color from the color palette. + * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) + */ + if (colors.length > 1) + { + for(i=0;i'; + + result+= ''+chartConf.additionalData.serie.value+'
' + pointDate + '| ' + this.series.yAxis.categories[this.point.y] + ': ' + + prefix + " " +newValue + " " + postfix + ' '; + + return result; + }; + tooltipObject={ + formatter:tooltipFormatter, + useHTML: true, + borderWidth: chartConf.tooltip.borderWidth, + borderRadius: chartConf.tooltip.borderRadius, + backgroundColor: chartConf.tooltip.backgroundColor ? chartConf.tooltip.backgroundColor: "", + + }; + + } else { + xAxisObject={ + type: 'category', + categories:chartConf.additionalData.firstCategory, + title: + { + text: (chartConf.xaxis.title.text!=undefined && chartConf.xaxis.title.text!="") ? chartConf.xaxis.title.text : undefined, + align: chartConf.xaxis.title.align, + + style: + { + color: (chartConf.xaxis.title.style.color!=undefined && chartConf.xaxis.title.style.color!="" && chartConf.xaxis.title.style.color!="transparent") ? chartConf.xaxis.title.style.color : '', + fontStyle: (chartConf.xaxis.title.style.fontStyle!=undefined && chartConf.xaxis.title.style.fontStyle!="") ? chartConf.xaxis.title.style.fontStyle : '', + textDecoration: (chartConf.xaxis.title.style.textDecoration!=undefined && chartConf.xaxis.title.style.textDecoration!="") ? chartConf.xaxis.title.style.textDecoration : '', + fontSize: (chartConf.xaxis.title.style.fontSize!=undefined && chartConf.xaxis.title.style.fontSize!="") ? chartConf.xaxis.title.style.fontSize : '', + fontFamily:(chartConf.xaxis.title.style.fontFamily!=undefined && chartConf.xaxis.title.style.fontFamily!="") ? chartConf.xaxis.title.style.fontFamily : '' + } + }, + + labels: { + + // x: 5, + // y: 15, + rotation: (chartConf.xaxis.labels.rotation!=undefined && chartConf.xaxis.labels.rotation!="") ? chartConf.xaxis.labels.rotation : 0, + align: (chartConf.xaxis.labels.align!=undefined && chartConf.xaxis.labels.align!="") ? chartConf.xaxis.labels.align : undefined, + style:{ + color: (chartConf.xaxis.labels.style.color!=undefined && chartConf.xaxis.labels.style.color!="" && chartConf.xaxis.labels.style.color!="transparent") ? chartConf.xaxis.labels.style.color : '', + fontStyle:(chartConf.xaxis.labels.style.fontStyle!=undefined && chartConf.xaxis.labels.style.fontStyle!="") ? chartConf.xaxis.labels.style.fontStyle : '', + textDecoration: (chartConf.xaxis.labels.style.textDecoration!=undefined && chartConf.xaxis.labels.style.textDecoration!="") ? chartConf.xaxis.labels.style.textDecoration : '', + fontSize: (chartConf.xaxis.labels.style.fontSize!=undefined && chartConf.xaxis.labels.style.fontSize!="") ? chartConf.xaxis.labels.style.fontSize : '', + fontFamily: (chartConf.xaxis.labels.style.fontFamily!=undefined && chartConf.xaxis.labels.style.fontFamily!="") ? chartConf.xaxis.labels.style.fontFamily : '', + } + }, + + showLastLabel: true, +// tickInterval:1, + tickLength: 16 + }; + serieColSize=1; + tooltipFormatter= function () { + + var color = chartConf.tooltip.color ? chartConf.tooltip.color : ''; + var align = chartConf.tooltip.align ? chartConf.tooltip.align : ''; + var fontFamily = chartConf.tooltip.fontFamily ? ' ' + chartConf.tooltip.fontFamily : ''; + var fontSize = chartConf.tooltip.fontSize ? ' ' + chartConf.tooltip.fontSize : ''; + var fontWeight = chartConf.tooltip.fontWeight ? ' ' + chartConf.tooltip.fontWeight : ''; + var tooltipFontStyle = ""; + + if (fontWeight == " underline") + { + tooltipFontStyle = " text-decoration: underline;"; + } + else if (fontWeight == " italic") + { + tooltipFontStyle = "font-style: italic;"; + } + else if (fontWeight == " bold") + { + tooltipFontStyle = "font-weight: bold;"; + } + else + { + tooltipFontStyle = "font-weight: normal;"; + } + + + var decimalPoints = Highcharts.getOptions().lang.decimalPoint; + var thousandsSep = Highcharts.getOptions().lang.thousandsSep; + var value = this.point.value; + var newValue = ""; + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + /* No selection is provided for the number to be displayed as the data label (pure value). */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + case "K": + newValue += Highcharts.numberFormat(value/Math.pow(10,3),precision,decimalPoints,thousandsSep) + "k"; + break; + case "M": + newValue += Highcharts.numberFormat(value/Math.pow(10,6),precision,decimalPoints,thousandsSep) + "M"; + break; + case "G": + newValue += Highcharts.numberFormat(value/Math.pow(10,9),precision,decimalPoints,thousandsSep) + "G"; + break; + case "T": + newValue += Highcharts.numberFormat(value/Math.pow(10,12),precision,decimalPoints,thousandsSep) + "T"; + break; + case "P": + newValue += Highcharts.numberFormat(value/Math.pow(10,15),precision,decimalPoints,thousandsSep) + "P"; + break; + case "E": + newValue += Highcharts.numberFormat(value/Math.pow(10,18),precision,decimalPoints,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + + } + var result = ""; + result += + '
'; + + result += ''+chartConf.additionalData.serie.value+'
' + this.series.xAxis.categories[this.point.x] + ' | ' + this.series.yAxis.categories[this.point.y] + ': ' + + prefix + " " +newValue + " " + postfix + '
'; + + + return result; + + }; + + tooltipObject={ + formatter:tooltipFormatter, + useHTML: true, + borderWidth: chartConf.tooltip.borderWidth, + borderRadius: chartConf.tooltip.borderRadius, + backgroundColor: chartConf.tooltip.backgroundColor ? chartConf.tooltip.backgroundColor: "", + + }; + + } + + var toReturn = { + + chart: chartObject, + + title: { + text: chartConf.title.text, + align: chartConf.title.style.textAlign, + style: { + color: chartConf.title.style.fontColor, + fontSize: chartConf.title.style.fontSize, + fontFamily: chartConf.title.style.fontFamily, + fontStyle: chartConf.title.style.fontStyle ? chartConf.title.style.fontStyle : "none", + textDecoration: chartConf.title.style.textDecoration ? chartConf.title.style.textDecoration : "none", + fontWeight: chartConf.title.style.fontWeight ? chartConf.title.style.fontWeight : "none" + } + }, + subtitle: { + text: chartConf.subtitle.text, + align: chartConf.subtitle.style.textAlign, + style: { + color: chartConf.subtitle.style.fontColor, + fontSize: chartConf.subtitle.style.fontSize, + fontFamily: chartConf.subtitle.style.fontFamily, + fontStyle: chartConf.subtitle.style.fontStyle ? chartConf.subtitle.style.fontStyle : "none", + textDecoration: chartConf.subtitle.style.textDecoration ? chartConf.subtitle.style.textDecoration : "none", + fontWeight: chartConf.subtitle.style.fontWeight ? chartConf.subtitle.style.fontWeight : "none" + } + }, + lang: { + noData : chartConf.emptymessage.text + }, + noData: { + style: { + color: chartConf.emptymessage.style.fontColor, + fontSize: chartConf.emptymessage.style.fontSize, + fontFamily: chartConf.emptymessage.style.fontFamily, + fontStyle: chartConf.emptymessage.style.fontStyle ? chartConf.emptymessage.style.fontStyle : "none", + textDecoration: chartConf.emptymessage.style.textDecoration ? chartConf.emptymessage.style.textDecoration : "none", + fontWeight: chartConf.emptymessage.style.fontWeight ? chartConf.emptymessage.style.fontWeight : "none" + }, + position: { + align: chartConf.emptymessage.style.textAlign, + verticalAlign: 'middle' + } + }, + + xAxis: xAxisObject, + + yAxis: + { + title: + { + text: (chartConf.yaxis.title.text!=undefined && chartConf.yaxis.title.text!="") ? chartConf.yaxis.title.text : undefined, + align:(chartConf.yaxis.title.align!=undefined && chartConf.yaxis.title.align!="")?chartConf.yaxis.title.align:undefined, + + /** + * Fixed value for margin of the Y-axis title. If the alignment of labels of the Y-axis + * is "right", then take the value of 40 (default one, provided by the Highcharts library + * for this property. + * + * @author: danristo (danilo.ristovski@mht.net) + */ + margin: (chartConf.yaxis.labels.align!=undefined && chartConf.yaxis.labels.align!="" && chartConf.yaxis.labels.align!="right") ? 60 : 40, + + style: + { + color: (chartConf.yaxis.title.style.color!=undefined && chartConf.yaxis.title.style.color!="" && chartConf.yaxis.title.style.color!="transparent" ) ? chartConf.yaxis.title.style.color : '', + fontStyle: (chartConf.yaxis.title.style.fontStyle!=undefined && chartConf.yaxis.title.style.fontStyle!="") ? chartConf.yaxis.title.style.fontStyle : '', + textDecoration: (chartConf.yaxis.title.style.textDecoration!=undefined && chartConf.yaxis.title.style.textDecoration!="") ? chartConf.yaxis.title.style.textDecoration : '', + fontSize: (chartConf.yaxis.title.style.fontSize!=undefined && chartConf.yaxis.title.style.fontSize!="") ? chartConf.yaxis.title.style.fontSize : '', + fontFamily:(chartConf.yaxis.title.style.fontFamily!=undefined && chartConf.yaxis.title.style.fontFamily!="") ? chartConf.yaxis.title.style.fontFamily : '' + } + }, + labels:{ + rotation: (chartConf.yaxis.labels.rotation!=undefined && chartConf.yaxis.labels.rotation!="") ? chartConf.yaxis.labels.rotation : 0, + align: (chartConf.yaxis.labels.align!=undefined && chartConf.yaxis.labels.align!="") ? chartConf.yaxis.labels.align : '', + + /** + * Provide the perfect left alignment when this one is selected (picked) by the user + * for the labels alignment. + * + * @author: danristo (danilo.ristovski@mht.net) + */ + /** + * makes padding when the alignment is right + */ + x:-10, + + style:{ + color: (chartConf.yaxis.labels.style.color!=undefined && chartConf.yaxis.labels.style.color!="" && chartConf.yaxis.labels.style.color!="transparent" ) ? chartConf.yaxis.labels.style.color : undefined, + fontStyle:(chartConf.yaxis.labels.style.fontStyle!=undefined && chartConf.yaxis.labels.style.fontStyle!="") ? chartConf.yaxis.labels.style.fontStyle : '', + textDecoration: (chartConf.yaxis.labels.style.textDecoration!=undefined && chartConf.yaxis.labels.style.textDecoration!="") ? chartConf.yaxis.labels.style.textDecoration : '', + fontSize: (chartConf.yaxis.labels.style.fontSize!=undefined && chartConf.yaxis.labels.style.fontSize!="") ? chartConf.yaxis.labels.style.fontSize : "", + fontFamily: (chartConf.yaxis.labels.style.fontFamily!=undefined && chartConf.yaxis.labels.style.fontFamily!="") ? chartConf.yaxis.labels.style.fontFamily : "", + } + }, + categories:chartConf.additionalData.storeresult, + reversed: false + }, + + /** + * Vertical legend of the HEATMAP will be positioned on the right side of the chart + * always (fixed values). Dynamic values are ones that user specifies for the height + * of the legend and its position relative to the vertical orientation (top, middle, + * bottom). + * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) + */ + legend: + { enabled: chartConf.legend.enabled, + align: 'right', + layout: 'vertical', + verticalAlign: chartConf.legend.style.align, + //y: (Number(chartHeight)-Number(chartConf.legend.symbolHeight))/2, + symbolHeight: Number(chartConf.legend.symbolHeight), + + /** + * Title for the HEATMAP legend (KNOWAGE-835 JIRA issue). + * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) + */ + title: { + + text: chartConf.legend.title.text, + + style: { + + color: chartConf.legend.title.style.color, + fontFamily: chartConf.legend.title.style.fontFamily, + fontSize: chartConf.legend.title.style.fontSize, + fontWeight: chartConf.legend.title.style.fontWeight + + } + + } + }, + + tooltip: tooltipObject, + series: [{ + borderWidth: 0, + nullColor: '#EFEFEF', + colsize: serieColSize, + data:points, + events: { + click: function(event){ + if(!exportWebApp){ + if(chartConf.chart.isCockpit==true){ + if(chartConf.chart.outcomingEventsEnabled){ + var selectParams = getCrossParamsForHeatmap(event.point,chartConf); + handleCockpitSelection(selectParams); + } + }else{ + + + var params=getCrossParamsForHeatmap(event.point,chartConf); + handleCrossNavigationTo(params); + + } + } + + } + }, + turboThreshold: Number.MAX_VALUE// #3404, remove after 4.0.5 release + }], + + + /** + * Credits option disabled/enabled for the HEATMAP chart. This option (boolean value) + * is defined inside of the VM for the HEATMAP chart. If enabled credits link appears + * in the right bottom part of the chart. + * @author: danristo (danilo.ristovski@mht.net) + */ + credits: + { + enabled: (chartConf.credits.enabled!=undefined) ? chartConf.credits.enabled : false + } + }; + + /** + * If there are no colors set in the color palette for the HEATMAP + * chart, exclude 'colorAxis' property from the chart configuration + * because we do not have a color that will server as an end color + * of the color interval (there are no colors available within the + * template). + * + * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) + */ + if (colors.length!=undefined) + { + toReturn['colorAxis'] = + { + stops:colorStops , + min: minValue, + max: maxValue, + startOnTick: false, + endOnTick: false, + labels: + { + format: '{value}' + } + }; + } + + + if(chartConf.additionalData.differentOrdering && chartConf.additionalData.storeresultOrder){ + var categories = [] + for(i=0;i Object.keys(chartConf.data[0]).length) { - chartConf.colors.length = Object.keys(chartConf.data[0]).length; - colors = chartConf.colors; + if(chartConf.colors.length ==0) { + colors = Highcharts.getOptions().colors; } else { - for (var i = 0; i < defaultColors.length; i++) { - if(defaultColors[i] != 'transparent') { - colors.push(defaultColors[i]) - } - if(colors.length == Object.keys(chartConf.data[0]).length){ - break; - } - } + colors = chartConf.colors; + } + while(chartConf.colors.length < Object.keys(chartConf.data[0]).length) { + colors = colors.concat(defaultColors) } /** @@ -94,12 +86,14 @@ function prepareChartConfForSunburst(chartConf, handleCockpitSelection, handleCr var legendCategories = []; precision = chartConf.series.precision ? chartConf.series.precision : ""; + scaleFactor = chartConf.series.scaleFactor ? chartConf.series.scaleFactor : "empty"; var center = { id: '0.0', parent: '', name: centerText } - points.push(center); + if(Object.keys(chartConf.data[0]).length) + points.push(center); var counter=0; @@ -200,11 +194,8 @@ function prepareChartConfForSunburst(chartConf, handleCockpitSelection, handleCr var chartObject = null; - if (chartConf.chart.height=="" - || chartConf.chart.width=="") - { - chartObject = - { + if (chartConf.chart.height=="" || chartConf.chart.width=="") { + chartObject = { //zoomType: 'xy', // Causes problems when zooming out (Zoom reset) (danristo) marginTop: chartConf.chart.marginTop ? chartConf.chart.marginTop : undefined, @@ -219,19 +210,19 @@ function prepareChartConfForSunburst(chartConf, handleCockpitSelection, handleCr fontSize: chartConf.chart.style.fontSize, fontWeight: chartConf.chart.style.fontWeight, fontStyle: chartConf.chart.style.fontStyle ? chartConf.chart.style.fontStyle : "", - textDecoration: chartConf.chart.style.textDecoration ? chartConf.chart.style.textDecoration : "", - fontWeight: chartConf.chart.style.fontWeight ? chartConf.chart.style.fontWeight : "" + textDecoration: chartConf.chart.style.textDecoration ? chartConf.chart.style.textDecoration : "", + fontWeight: chartConf.chart.style.fontWeight ? chartConf.chart.style.fontWeight : "" } }; - if (chartConf.chart.backgroundColor!=undefined && chartConf.chart.backgroundColor!="") - chartObject.backgroundColor = chartConf.chart.backgroundColor; + if (chartConf.chart.style.backgroundColor!=undefined && chartConf.chart.style.backgroundColor!="") + chartObject.backgroundColor = chartConf.chart.style.backgroundColor; + /*chartObject.plotBorderWidth = 0; + chartObject.plotBackgroundColor = chartConf.chart.style.backgroundColor; + chartObject.plotShadow = false;*/ } - else if (chartConf.chart.height!="" - && chartConf.chart.width!="") - { - chartObject = - { + else if (chartConf.chart.height!="" && chartConf.chart.width!="") { + chartObject = { //zoomType: 'xy', // Causes problems when zooming out (Zoom reset) (danristo) marginTop: chartConf.chart.marginTop ? chartConf.chart.marginTop : undefined, @@ -246,32 +237,102 @@ function prepareChartConfForSunburst(chartConf, handleCockpitSelection, handleCr fontSize: chartConf.chart.style.fontSize, fontWeight: chartConf.chart.style.fontWeight, fontStyle: chartConf.chart.style.fontStyle ? chartConf.chart.style.fontStyle : "", - textDecoration: chartConf.chart.style.textDecoration ? chartConf.chart.style.textDecoration : "", - fontWeight: chartConf.chart.style.fontWeight ? chartConf.chart.style.fontWeight : "" + textDecoration: chartConf.chart.style.textDecoration ? chartConf.chart.style.textDecoration : "", + fontWeight: chartConf.chart.style.fontWeight ? chartConf.chart.style.fontWeight : "" } }; if(!exportWebApp){ - chartObject = - { - height: chartConf.chart.height ? Number(chartConf.chart.height) : undefined, - width: chartConf.chart.width ? Number(chartConf.chart.width) : undefined, - }; + chartObject.height = chartConf.chart.height ? Number(chartConf.chart.height) : undefined; + chartObject.width = chartConf.chart.width ? Number(chartConf.chart.width) : undefined; } - if (chartConf.chart.backgroundColor!=undefined && chartConf.chart.backgroundColor!="") - chartObject.backgroundColor = chartConf.chart.backgroundColor; + if (chartConf.chart.style.backgroundColor!=undefined && chartConf.chart.style.backgroundColor!="") + chartObject.backgroundColor = chartConf.chart.style.backgroundColor; + /*chartObject.plotBorderWidth = 0; + chartObject.plotBackgroundColor = chartConf.chart.style.backgroundColor; + chartObject.plotShadow = false;*/ } var tooltipObject={}; prefix = chartConf.series.prefixChar ? chartConf.series.prefixChar : ""; postfix = chartConf.series.postfixChar ? chartConf.series.postfixChar : ""; tooltipFormatter = function () { - var val = this.point.value.toFixed(precision); - return this.point.name + ': ' + - prefix + " " +val + " " + postfix; + + var color = chartConf.tooltip.color ? chartConf.tooltip.color : ''; + var align = chartConf.tooltip.align ? chartConf.tooltip.align : ''; + var fontFamily = chartConf.tooltip.fontFamily ? ' ' + chartConf.tooltip.fontFamily : ''; + var fontSize = chartConf.tooltip.fontSize ? ' ' + chartConf.tooltip.fontSize : ''; + var fontWeight = chartConf.tooltip.fontWeight ? ' ' + chartConf.tooltip.fontWeight : ''; + var tooltipFontStyle = ""; + + if (fontWeight == " underline") + { + tooltipFontStyle = " text-decoration: underline;"; + } + else if (fontWeight == " italic") + { + tooltipFontStyle = "font-style: italic;"; + } + else if (fontWeight == " bold") + { + tooltipFontStyle = "font-weight: bold;"; + } + else + { + tooltipFontStyle = "font-weight: normal;"; + } + + var decimalPoints = Highcharts.getOptions().lang.decimalPoint; + var thousandsSep = Highcharts.getOptions().lang.thousandsSep; + var value = this.point.value; + var newValue = ""; + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + /* No selection is provided for the number to be displayed as the data label (pure value). */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + case "K": + newValue += Highcharts.numberFormat(value/Math.pow(10,3),precision,decimalPoints,thousandsSep) + "k"; + break; + case "M": + newValue += Highcharts.numberFormat(value/Math.pow(10,6),precision,decimalPoints,thousandsSep) + "M"; + break; + case "G": + newValue += Highcharts.numberFormat(value/Math.pow(10,9),precision,decimalPoints,thousandsSep) + "G"; + break; + case "T": + newValue += Highcharts.numberFormat(value/Math.pow(10,12),precision,decimalPoints,thousandsSep) + "T"; + break; + case "P": + newValue += Highcharts.numberFormat(value/Math.pow(10,15),precision,decimalPoints,thousandsSep) + "P"; + break; + case "E": + newValue += Highcharts.numberFormat(value/Math.pow(10,18),precision,decimalPoints,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + + } + var result = ""; + result += + '
'; + + result += '' + this.point.name + '
' + prefix + " " + newValue + " " + postfix + '
'; + + return result; + }; tooltipObject = { - formatter: tooltipFormatter, + formatter:tooltipFormatter, + useHTML: true, + borderWidth: chartConf.tooltip.borderWidth, + borderRadius: chartConf.tooltip.borderRadius, + backgroundColor: chartConf.tooltip.backgroundColor ? chartConf.tooltip.backgroundColor: "", }; var chart = { @@ -343,7 +404,7 @@ function prepareChartConfForSunburst(chartConf, handleCockpitSelection, handleCr fontWeight: chartConf.emptymessage.style.fontWeight ? chartConf.emptymessage.style.fontWeight : "none" }, position: { - align: chartConf.emptymessage.style.textAlign, + align: chartConf.emptymessage.style.align, verticalAlign: 'middle' } }, diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/treemap/treemap.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/treemap/treemap.js index 8bc3dc9d264..808037e05c8 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/treemap/treemap.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/chart/treemap/treemap.js @@ -65,102 +65,6 @@ function renderTreemap(chartConf,handleCockpitSelection, handleCrossNavigationTo // } } - - -function renderHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo, exportWebApp,advanced,chartConfMergeService ) { - - chartConfig = prepareChartConfForHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo, exportWebApp); - - chartConfMergeService.addProperty(advanced,chartConf); - - if (exportWebApp){ - return chartConfig; - } - var chart = new Highcharts.Chart(chartConfig); - - return chart; -// var getCrossParams= function(point){ -// var params={ -// point:{ -// name: null, // category name -// value: null, // category value -// crossNavigationDocumentName:null, -// crossNavigationDocumentParams:null, -// -// series:{ // serie name and value -// name:null, -// value: null -// }, -// group:{ // grouping category name and value -// name:null, -// value: null -// } -// } -// }; -// -// params.point.crossNavigationDocumentName=chartConf.crossNavigation.crossNavigationDocumentName; -// params.point.crossNavigationDocumentParams=chartConf.crossNavigation.crossNavigationDocumentParams; -// params.point.name=chartConf.additionalData.columns[0].value; -// params.point.value= new Date(point.x); -// params.point.series.name=chartConf.additionalData.serie.value; -// params.point.series.value=point.value; -// params.point.group.name=chartConf.additionalData.columns[1].value; -// params.point.group.value=point.label; -// -// return params; -// }; -} - -function getCrossParamsForHeatmap(point,chartConf){ - var params={ - point:{ - name: null, // category name - value: null, // category value - y:null, - crossNavigationDocumentName:null, - crossNavigationDocumentParams:null, - - series:{ // serie name and value - name:null, - y: null - }, - group:{ // grouping category name and value - name:null, - value: null - } - } - }; - - - - params.point.category=chartConf.additionalData.columns[0].value; - if(chartConf.chart.xAxisDate){ - params.point.name= point.original; - }else{ - params.point.name= chartConf.additionalData.firstCategory[point.x]; - } - params.point.series.name=chartConf.additionalData.serie.value; - params.point.y=point.value; - params.point.group.name=chartConf.additionalData.columns[1].value; - params.point.group.value=point.label; - - return params; - -} - -function getSelectionParammsForHeatmap(point,chartConf){ - var params={ - point:{ - name: null, // category name - value: null, // category value - } - }; - params.point.name=point.label; - params.point.value=point.value; - - return params; -} - function getCrossParamsForTreemap(point,chartConf){ var params={ point:{ @@ -264,6 +168,8 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross var counter=0; precision = chartConf.additionalData.precision ? chartConf.additionalData.precision : ""; + scaleFactor = chartConf.additionalData.scaleFactor ? chartConf.additionalData.scaleFactor : "empty"; + for (var dataset in chartConf.data[0]){ level = { id: "id_" + counter, @@ -338,11 +244,8 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross var chartObject = null; - if (chartConf.chart.height=="" - || chartConf.chart.width=="") - { - chartObject = - { + if (chartConf.chart.height=="" || chartConf.chart.width=="") { + chartObject = { //zoomType: 'xy', // Causes problems when zooming out (Zoom reset) (danristo) marginTop: chartConf.chart.marginTop ? chartConf.chart.marginTop : undefined, @@ -365,11 +268,8 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross if (chartConf.chart.backgroundColor!=undefined && chartConf.chart.backgroundColor!="") chartObject.backgroundColor = chartConf.chart.backgroundColor; } - else if (chartConf.chart.height!="" - && chartConf.chart.width!="") - { - chartObject = - { + else if (chartConf.chart.height!="" && chartConf.chart.width!="") { + chartObject = { //zoomType: 'xy', // Causes problems when zooming out (Zoom reset) (danristo) marginTop: chartConf.chart.marginTop ? chartConf.chart.marginTop : undefined, @@ -389,11 +289,8 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross } }; if(!exportWebApp){ - chartObject = - { - height: chartConf.chart.height ? Number(chartConf.chart.height) : undefined, - width: chartConf.chart.width ? Number(chartConf.chart.width) : undefined, - }; + chartObject.height = chartConf.chart.height ? Number(chartConf.chart.height) : undefined; + chartObject.width = chartConf.chart.width ? Number(chartConf.chart.width) : undefined; } if (chartConf.chart.backgroundColor!=undefined && chartConf.chart.backgroundColor!="") chartObject.backgroundColor = chartConf.chart.backgroundColor; @@ -404,6 +301,32 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross tooltipFormatter= function () { + var ttColor = chartConf.additionalData.tooltip.ttColor ? chartConf.additionalData.tooltip.ttColor : ''; + + var ttAlign = chartConf.additionalData.tooltip.ttAlign ? chartConf.additionalData.tooltip.ttAlign : ''; + var ttFont = chartConf.additionalData.tooltip.ttFont ? ' ' + chartConf.additionalData.tooltip.ttFont : ''; + var ttFontSize = chartConf.additionalData.tooltip.ttFontSize ? ' ' + chartConf.additionalData.tooltip.ttFontSize : ''; + var ttFontWeight = chartConf.additionalData.tooltip.ttFontWeight ? ' ' + chartConf.additionalData.tooltip.ttFontWeight : ''; + var tooltipFontStyle = ""; + + if (ttFontWeight == " underline") + { + tooltipFontStyle = " text-decoration: underline;"; + } + else if (ttFontWeight == " italic") + { + tooltipFontStyle = "font-style: italic;"; + } + else if (ttFontWeight == " bold") + { + tooltipFontStyle = "font-weight: bold;"; + } + else + { + tooltipFontStyle = "font-weight: normal;"; + } + + var point = this.point, group = this.series.data.filter(function (x) { @@ -417,22 +340,63 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross }, 0); percentage = 100 * point.value/groupTotal; + var decimalPoints = Highcharts.getOptions().lang.decimalPoint; + var thousandsSep = Highcharts.getOptions().lang.thousandsSep; + var value = this.point.value; + var newValue = ""; + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + /* No selection is provided for the number to be displayed as the data label (pure value). */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + case "K": + newValue += Highcharts.numberFormat(value/Math.pow(10,3),precision,decimalPoints,thousandsSep) + "k"; + break; + case "M": + newValue += Highcharts.numberFormat(value/Math.pow(10,6),precision,decimalPoints,thousandsSep) + "M"; + break; + case "G": + newValue += Highcharts.numberFormat(value/Math.pow(10,9),precision,decimalPoints,thousandsSep) + "G"; + break; + case "T": + newValue += Highcharts.numberFormat(value/Math.pow(10,12),precision,decimalPoints,thousandsSep) + "T"; + break; + case "P": + newValue += Highcharts.numberFormat(value/Math.pow(10,15),precision,decimalPoints,thousandsSep) + "P"; + break; + case "E": + newValue += Highcharts.numberFormat(value/Math.pow(10,18),precision,decimalPoints,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + + } + var result = ""; + result += + '
'; if(!chartConf.additionalData.showAbsValue && !chartConf.additionalData.showPercentage){ - return point.name + '
'; + result += '' + point.name + '
'; } else if (!chartConf.additionalData.showAbsValue && chartConf.additionalData.showPercentage){ - return point.name + '
' + percentage.toFixed(precision) + '%'; - + result += '' + point.name + '
'+ percentage.toFixed(precision) + '%

'; } else if (chartConf.additionalData.showAbsValue && !chartConf.additionalData.showPercentage ){ - return point.name + '
'+ prefix +" "+ point.value.toFixed(precision) +" "+ postfix; - + result += '' + point.name + '
'+ newValue +" "+ postfix + '
'; } else if(chartConf.additionalData.showAbsValue && chartConf.additionalData.showPercentage){ - return point.name + '
' + percentage.toFixed(precision) + '%' + '
'+prefix +" "+ point.value.toFixed(precision) +" "+ postfix; + result += '' + point.name + '
'+ percentage.toFixed(precision) + '%' + '
'+prefix +" "+newValue +" "+ postfix +'

'; } - + return result; }; tooltipObject={ + borderWidth: chartConf.tooltip.borderWidth, + borderRadius: chartConf.tooltip.borderRadius, + useHTML: true, + backgroundColor: chartConf.additionalData.tooltip.ttBackColor, formatter:tooltipFormatter, }; @@ -517,12 +481,48 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross enabled: true, formatter: function() { - var point = this.point, + var point = this.point group = this.series.data.filter(function (x) { return x.parent === point.parent; }); + var decimalPoints = Highcharts.getOptions().lang.decimalPoint; + var thousandsSep = Highcharts.getOptions().lang.thousandsSep; + var value = this.point.value; + var newValue = ""; + switch(scaleFactor.toUpperCase()) { + + case "EMPTY": + /* No selection is provided for the number to be displayed as the data label (pure value). */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + case "K": + newValue += Highcharts.numberFormat(value/Math.pow(10,3),precision,decimalPoints,thousandsSep) + "k"; + break; + case "M": + newValue += Highcharts.numberFormat(value/Math.pow(10,6),precision,decimalPoints,thousandsSep) + "M"; + break; + case "G": + newValue += Highcharts.numberFormat(value/Math.pow(10,9),precision,decimalPoints,thousandsSep) + "G"; + break; + case "T": + newValue += Highcharts.numberFormat(value/Math.pow(10,12),precision,decimalPoints,thousandsSep) + "T"; + break; + case "P": + newValue += Highcharts.numberFormat(value/Math.pow(10,15),precision,decimalPoints,thousandsSep) + "P"; + break; + case "E": + newValue += Highcharts.numberFormat(value/Math.pow(10,18),precision,decimalPoints,thousandsSep) + "E"; + break; + default: + /* The same as for the case when user picked "no selection" - in case when the chart + template does not contain the scale factor for current serie */ + newValue += Highcharts.numberFormat(value,precision,decimalPoints,thousandsSep); + break; + + } + var groupTotal = group.map(function (x) { return x.value; }).reduce(function (a, b) { @@ -537,10 +537,10 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross return point.name + '
' + percentage.toFixed(precision) + '%'; } else if (chartConf.additionalData.showAbsValue && !chartConf.additionalData.showPercentage ){ - return point.name + '
'+ prefix +" "+ point.value.toFixed(precision) +" "+ postfix; + return point.name + '
'+ prefix +" "+ newValue +" "+ postfix; } else if(chartConf.additionalData.showAbsValue && chartConf.additionalData.showPercentage){ - return point.name + '
' + percentage.toFixed(precision) + '%' + '
'+prefix +" "+ point.value.toFixed(precision) +" "+ postfix; + return point.name + '
' + percentage.toFixed(precision) + '%' + '
'+prefix +" "+ newValue +" "+ postfix; } /* for(var i = 0 ; i < this.point.node.children.length;i++){ @@ -656,522 +656,3 @@ function prepareChartConfForTreemap(chartConf,handleCockpitSelection,handleCross }; } - -function prepareChartConfForHeatmap(chartConf,handleCockpitSelection,handleCrossNavigationTo,exportWebApp) { - var start; - var startDate; - var endDate; - if(chartConf.chart.xAxisDate){ - startDate= new Date(chartConf.additionalData.firstCategory[0]); - endDate= new Date(chartConf.additionalData.firstCategory[1]); - } - var points=[]; - var data=chartConf.data[0]; - var minValue=data.length >0 ? data[0][chartConf.additionalData.serie.value] : 0; - var maxValue=data.length >0 ? data[0][chartConf.additionalData.serie.value] :0; - - for( i=0;i maxValue){ - maxValue=data[i][chartConf.additionalData.serie.value]; - } - - var xValue; - var xValueOriginal; - if(chartConf.chart.xAxisDate){ - xValue=new Date(data[i][chartConf.additionalData.columns[0].value]).getTime(); - xValueOriginal =data[i][chartConf.additionalData.columns[0].value]; - }else{ - xValue=chartConf.additionalData.firstCategory.indexOf(data[i][chartConf.additionalData.columns[0].value]); - } - var point={ - "x":xValue, - "original":xValueOriginal, - "y":chartConf.additionalData.storeresult.indexOf(data[i][chartConf.additionalData.columns[1].value]), - "value":data[i][chartConf.additionalData.serie.value], - "label":data[i][chartConf.additionalData.columns[1].value] - }; - - points.push(point); - } - - var colors=chartConf.colors; - var colorStops=[]; - - /** - * Provide the ending color for the color interval of the HEATMAP - * if there is one for that. Otherwise, skip this snippet. - * - * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - if (colors.length) - { - /** - * Check if user specified only 1 color from the color palette. - * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - if (colors.length > 1) - { - for(i=0;i'+chartConf.additionalData.serie.value+'

' + pointDate + '| ' + this.series.yAxis.categories[this.point.y] + ': ' + - prefix + " " +val + " " + postfix + ' '; - }; - tooltipObject={ - formatter:tooltipFormatter, - style:{ - color: chartConf.tooltip.style.fontColor, - fontSize: chartConf.tooltip.style.fontSize, - fontFamily: chartConf.tooltip.style.fontFamily - } - }; - - } else { - xAxisObject={ - type: 'category', - categories:chartConf.additionalData.firstCategory, - title: - { - text: (chartConf.xaxis.title.text!=undefined && chartConf.xaxis.title.text!="") ? chartConf.xaxis.title.text : undefined, - align: chartConf.xaxis.title.align, - - style: - { - color: (chartConf.xaxis.title.style.color!=undefined && chartConf.xaxis.title.style.color!="" && chartConf.xaxis.title.style.color!="transparent") ? chartConf.xaxis.title.style.color : '', - fontStyle: (chartConf.xaxis.title.style.fontStyle!=undefined && chartConf.xaxis.title.style.fontStyle!="") ? chartConf.xaxis.title.style.fontStyle : '', - textDecoration: (chartConf.xaxis.title.style.textDecoration!=undefined && chartConf.xaxis.title.style.textDecoration!="") ? chartConf.xaxis.title.style.textDecoration : '', - fontSize: (chartConf.xaxis.title.style.fontSize!=undefined && chartConf.xaxis.title.style.fontSize!="") ? chartConf.xaxis.title.style.fontSize : '', - fontFamily:(chartConf.xaxis.title.style.fontFamily!=undefined && chartConf.xaxis.title.style.fontFamily!="") ? chartConf.xaxis.title.style.fontFamily : '' - } - }, - - labels: { - - // x: 5, - // y: 15, - rotation: (chartConf.xaxis.labels.rotation!=undefined && chartConf.xaxis.labels.rotation!="") ? chartConf.xaxis.labels.rotation : 0, - align: (chartConf.xaxis.labels.align!=undefined && chartConf.xaxis.labels.align!="") ? chartConf.xaxis.labels.align : undefined, - style:{ - color: (chartConf.xaxis.labels.style.color!=undefined && chartConf.xaxis.labels.style.color!="" && chartConf.xaxis.labels.style.color!="transparent") ? chartConf.xaxis.labels.style.color : '', - fontStyle:(chartConf.xaxis.labels.style.fontStyle!=undefined && chartConf.xaxis.labels.style.fontStyle!="") ? chartConf.xaxis.labels.style.fontStyle : '', - textDecoration: (chartConf.xaxis.labels.style.textDecoration!=undefined && chartConf.xaxis.labels.style.textDecoration!="") ? chartConf.xaxis.labels.style.textDecoration : '', - fontSize: (chartConf.xaxis.labels.style.fontSize!=undefined && chartConf.xaxis.labels.style.fontSize!="") ? chartConf.xaxis.labels.style.fontSize : '', - fontFamily: (chartConf.xaxis.labels.style.fontFamily!=undefined && chartConf.xaxis.labels.style.fontFamily!="") ? chartConf.xaxis.labels.style.fontFamily : '', - } - }, - - showLastLabel: true, -// tickInterval:1, - tickLength: 16 - }; - serieColSize=1; - tooltipFormatter= function () { - var val = this.point.value; - val = Highcharts.numberFormat(val,precision ); - return ''+chartConf.additionalData.serie.value+'
' + this.series.xAxis.categories[this.point.x] + ' | ' + this.series.yAxis.categories[this.point.y] + ': ' + - prefix + " " +val + " " + postfix + ' '; - }; - - tooltipObject={ - formatter:tooltipFormatter, - style:{ - color: chartConf.tooltip.style.fontColor, - fontSize: chartConf.tooltip.style.fontSize, - fontFamily: chartConf.tooltip.style.fontFamily - } - }; - } - - var toReturn = { - - chart: chartObject, - - title: { - text: chartConf.title.text, - align: chartConf.title.style.textAlign, - style: { - color: chartConf.title.style.fontColor, - fontSize: chartConf.title.style.fontSize, - fontFamily: chartConf.title.style.fontFamily, - fontStyle: chartConf.title.style.fontStyle ? chartConf.title.style.fontStyle : "none", - textDecoration: chartConf.title.style.textDecoration ? chartConf.title.style.textDecoration : "none", - fontWeight: chartConf.title.style.fontWeight ? chartConf.title.style.fontWeight : "none" - } - }, - subtitle: { - text: chartConf.subtitle.text, - align: chartConf.subtitle.style.textAlign, - style: { - color: chartConf.subtitle.style.fontColor, - fontSize: chartConf.subtitle.style.fontSize, - fontFamily: chartConf.subtitle.style.fontFamily, - fontStyle: chartConf.subtitle.style.fontStyle ? chartConf.subtitle.style.fontStyle : "none", - textDecoration: chartConf.subtitle.style.textDecoration ? chartConf.subtitle.style.textDecoration : "none", - fontWeight: chartConf.subtitle.style.fontWeight ? chartConf.subtitle.style.fontWeight : "none" - } - }, - lang: { - noData : chartConf.emptymessage.text - }, - noData: { - style: { - color: chartConf.emptymessage.style.fontColor, - fontSize: chartConf.emptymessage.style.fontSize, - fontFamily: chartConf.emptymessage.style.fontFamily, - fontStyle: chartConf.emptymessage.style.fontStyle ? chartConf.emptymessage.style.fontStyle : "none", - textDecoration: chartConf.emptymessage.style.textDecoration ? chartConf.emptymessage.style.textDecoration : "none", - fontWeight: chartConf.emptymessage.style.fontWeight ? chartConf.emptymessage.style.fontWeight : "none" - }, - position: { - align: chartConf.emptymessage.style.textAlign, - verticalAlign: 'middle' - } - }, - - xAxis: xAxisObject, - - yAxis: - { - title: - { - text: (chartConf.yaxis.title.text!=undefined && chartConf.yaxis.title.text!="") ? chartConf.yaxis.title.text : undefined, - align:(chartConf.yaxis.title.align!=undefined && chartConf.yaxis.title.align!="")?chartConf.yaxis.title.align:undefined, - - /** - * Fixed value for margin of the Y-axis title. If the alignment of labels of the Y-axis - * is "right", then take the value of 40 (default one, provided by the Highcharts library - * for this property. - * - * @author: danristo (danilo.ristovski@mht.net) - */ - margin: (chartConf.yaxis.labels.align!=undefined && chartConf.yaxis.labels.align!="" && chartConf.yaxis.labels.align!="right") ? 60 : 40, - - style: - { - color: (chartConf.yaxis.title.style.color!=undefined && chartConf.yaxis.title.style.color!="" && chartConf.yaxis.title.style.color!="transparent" ) ? chartConf.yaxis.title.style.color : '', - fontStyle: (chartConf.yaxis.title.style.fontStyle!=undefined && chartConf.yaxis.title.style.fontStyle!="") ? chartConf.yaxis.title.style.fontStyle : '', - textDecoration: (chartConf.yaxis.title.style.textDecoration!=undefined && chartConf.yaxis.title.style.textDecoration!="") ? chartConf.yaxis.title.style.textDecoration : '', - fontSize: (chartConf.yaxis.title.style.fontSize!=undefined && chartConf.yaxis.title.style.fontSize!="") ? chartConf.yaxis.title.style.fontSize : '', - fontFamily:(chartConf.yaxis.title.style.fontFamily!=undefined && chartConf.yaxis.title.style.fontFamily!="") ? chartConf.yaxis.title.style.fontFamily : '' - } - }, - labels:{ - rotation: (chartConf.yaxis.labels.rotation!=undefined && chartConf.yaxis.labels.rotation!="") ? chartConf.yaxis.labels.rotation : 0, - align: (chartConf.yaxis.labels.align!=undefined && chartConf.yaxis.labels.align!="") ? chartConf.yaxis.labels.align : '', - - /** - * Provide the perfect left alignment when this one is selected (picked) by the user - * for the labels alignment. - * - * @author: danristo (danilo.ristovski@mht.net) - */ - /** - * makes padding when the alignment is right - */ - x:-10, - - style:{ - color: (chartConf.yaxis.labels.style.color!=undefined && chartConf.yaxis.labels.style.color!="" && chartConf.yaxis.labels.style.color!="transparent" ) ? chartConf.yaxis.labels.style.color : undefined, - fontStyle:(chartConf.yaxis.labels.style.fontStyle!=undefined && chartConf.yaxis.labels.style.fontStyle!="") ? chartConf.yaxis.labels.style.fontStyle : '', - textDecoration: (chartConf.yaxis.labels.style.textDecoration!=undefined && chartConf.yaxis.labels.style.textDecoration!="") ? chartConf.yaxis.labels.style.textDecoration : '', - fontSize: (chartConf.yaxis.labels.style.fontSize!=undefined && chartConf.yaxis.labels.style.fontSize!="") ? chartConf.yaxis.labels.style.fontSize : "", - fontFamily: (chartConf.yaxis.labels.style.fontFamily!=undefined && chartConf.yaxis.labels.style.fontFamily!="") ? chartConf.yaxis.labels.style.fontFamily : "", - } - }, - categories:chartConf.additionalData.storeresult, - reversed: false - }, - - /** - * Vertical legend of the HEATMAP will be positioned on the right side of the chart - * always (fixed values). Dynamic values are ones that user specifies for the height - * of the legend and its position relative to the vertical orientation (top, middle, - * bottom). - * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - legend: - { enabled: chartConf.legend.enabled, - align: 'right', - layout: 'vertical', - verticalAlign: chartConf.legend.style.align, - //y: (Number(chartHeight)-Number(chartConf.legend.symbolHeight))/2, - symbolHeight: Number(chartConf.legend.symbolHeight), - - /** - * Title for the HEATMAP legend (KNOWAGE-835 JIRA issue). - * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - title: { - - text: chartConf.legend.title.text, - - style: { - - color: chartConf.legend.title.style.color, - fontFamily: chartConf.legend.title.style.fontFamily, - fontSize: chartConf.legend.title.style.fontSize, - fontWeight: chartConf.legend.title.style.fontWeight - - } - - } - }, - - tooltip: tooltipObject, - series: [{ - borderWidth: 0, - nullColor: '#EFEFEF', - colsize: serieColSize, - data:points, - events: { - click: function(event){ - if(!exportWebApp){ - if(chartConf.chart.isCockpit==true){ - if(chartConf.chart.outcomingEventsEnabled){ - var selectParams = getCrossParamsForHeatmap(event.point,chartConf); - handleCockpitSelection(selectParams); - } - }else{ - - - var params=getCrossParamsForHeatmap(event.point,chartConf); - handleCrossNavigationTo(params); - - } - } - - } - }, - turboThreshold: Number.MAX_VALUE// #3404, remove after 4.0.5 release - }], - - - /** - * Credits option disabled/enabled for the HEATMAP chart. This option (boolean value) - * is defined inside of the VM for the HEATMAP chart. If enabled credits link appears - * in the right bottom part of the chart. - * @author: danristo (danilo.ristovski@mht.net) - */ - credits: - { - enabled: (chartConf.credits.enabled!=undefined) ? chartConf.credits.enabled : false - } - }; - - /** - * If there are no colors set in the color palette for the HEATMAP - * chart, exclude 'colorAxis' property from the chart configuration - * because we do not have a color that will server as an end color - * of the color interval (there are no colors available within the - * template). - * - * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - if (colors.length!=undefined) - { - toReturn['colorAxis'] = - { - stops:colorStops , - min: minValue, - max: maxValue, - startOnTick: false, - endOnTick: false, - labels: - { - format: '{value}' - } - }; - } - - return toReturn; -} \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/cockpit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/cockpit.js index bcbd0684bb5..27acbea54fb 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/cockpit.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/cockpit.js @@ -19,9 +19,10 @@ var isIE = window.document.documentMode; var scripts = document.getElementsByTagName("script"); var baseScriptPath = scripts[scripts.length - 1].src; baseScriptPath =baseScriptPath .substring(0, baseScriptPath .lastIndexOf('/')); +if(!agGrid) var agGrid = false; (function() { - agGrid.initialiseAgGridWithAngular1(angular); +if(agGrid) agGrid.initialiseAgGridWithAngular1(angular); var cockpitApp= angular.module("cockpitModule",[ 'ngMaterial', 'ngSanitize', @@ -37,9 +38,9 @@ var cockpitApp= angular.module("cockpitModule",[ 'chartRendererModule', 'jsonFormatter', 'ui.codemirror', - 'knModule', 'agGrid', - 'chartDesignerManager' + 'chartDesignerManager', + 'customWidgetAPI' ]); cockpitApp.config(function($mdThemingProvider,$mdGestureProvider,$compileProvider,$mdInkRippleProvider,$mdAriaProvider) { $mdThemingProvider.theme('knowage') diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/cockpitColumnsConfigurator.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/cockpitColumnsConfigurator.js index 6264d2546af..50680a1b307 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/cockpitColumnsConfigurator.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/cockpitColumnsConfigurator.js @@ -95,7 +95,6 @@ onGridReady : resizeColumns, onCellEditingStopped: refreshRow, singleClickEdit: true, - stopEditingWhenGridLosesFocus: true, columnDefs: [ //{headerName:'Order', cellRenderer: orderRenderer, field:'order',width: 100,suppressSizeToFit:true,sort: 'asc',"cellStyle":{"border":"none !important","display":"inline-flex","justify-content":"center"}}, {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.name'), field:'name',"editable":isInputEditable,cellRenderer:editableCell, cellClass: 'editableCell',rowDrag: true}, @@ -153,6 +152,7 @@ return typeof(params.data.name) !== 'undefined'; } function isAggregationEditable(params) { + if (params.data.isCalculated) return false; return params.data.fieldType == "MEASURE" ? true : false; } @@ -467,14 +467,36 @@ function controllerCockpitColumnsConfigurator($scope,sbiModule_translate,$mdDial } } -function cockpitStyleColumnFunction($scope,sbiModule_translate,$mdDialog,$mdPanel,model,selectedColumn,cockpitModule_generalServices,cockpitModule_datasetServices,$mdToast,cockpitModule_generalOptions,sbiModule_messaging,knModule_fontIconsService, cockpitModule_properties){ +function cockpitStyleColumnFunction( + $scope, + sbiModule_translate, + $mdDialog, + $mdPanel, + model, + selectedColumn, + cockpitModule_generalServices, + cockpitModule_datasetServices, + $mdToast, + cockpitModule_generalOptions, + sbiModule_messaging, + knModule_fontIconsService, + cockpitModule_properties, + dialogOptions) { + $scope.translate=sbiModule_translate; $scope.generalServices=cockpitModule_generalServices; $scope.cockpitModule_generalOptions=cockpitModule_generalOptions; $scope.cockpitModule_properties = cockpitModule_properties; - $scope.model = model; $scope.selectedColumn = angular.copy(selectedColumn); + + $scope.needsCommonPrefs = (typeof dialogOptions.needsCommonPrefs == 'undefined' ? true : dialogOptions.needsCommonPrefs); + $scope.needsVisualization = (typeof dialogOptions.needsVisualization == 'undefined' ? true : dialogOptions.needsVisualization); + $scope.needsThresholds = (typeof dialogOptions.needsThresholds == 'undefined' ? true : dialogOptions.needsThresholds); + $scope.needsFormat = (typeof dialogOptions.needsFormat == 'undefined' ? true : dialogOptions.needsFormat); + $scope.needsStyle = (typeof dialogOptions.needsStyle == 'undefined' ? true : dialogOptions.needsStyle); + $scope.needsTooltip = (typeof dialogOptions.needsTooltip == 'undefined' ? true : dialogOptions.needsTooltip); + $scope.modelTextAlign = {"flex-start":sbiModule_translate.load('sbi.cockpit.style.textAlign.left'),"center":sbiModule_translate.load('sbi.cockpit.style.textAlign.center'),"flex-end":sbiModule_translate.load('sbi.cockpit.style.textAlign.right')}; $scope.formatPattern = ['#.###','#,###','#.###,##','#,###.##']; $scope.colorPickerProperty={placeholder:sbiModule_translate.load('sbi.cockpit.color.select') ,format:'rgb'} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitCalculatedFieldTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitCalculatedFieldTemplate.html index cb4c6fd5b5d..948a77f84dd 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitCalculatedFieldTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitCalculatedFieldTemplate.html @@ -28,29 +28,34 @@

{{::translate.load('sbi.crosstab.calculatefieldwizard.tit
- - + + + + - - - - - {{func.label}} - - - - - {{::translate.load('sbi.cockpit.widgets.table.calculatedFields.datasetOrTableFlag')}} - - {{::translate.load('sbi.cockpit.widgets.table.calculatedFields.datasetOrTableFlag.hint')}} - - + + + + + + + + + + + + + +
+
+
{{showWarning}}
+
- + {{formula.syntax | limitTo:50}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html index 4baeca0ef64..d3f39d54687 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html @@ -13,7 +13,7 @@

{{::translate.load('sbi.cockpit.widgets.table.columnstyle')}}

-
+
@@ -49,7 +49,7 @@

{{::translate.load('sbi.cockpit.widgets.table.columnstyle')}}

-
+
@@ -100,7 +100,7 @@

{{::translate.load('sbi.cockpit.widgets.table.columnstyle')}}

- +

{{::translate.load('sbi.cockpit.table.threshold')}}

@@ -152,7 +152,7 @@

{{::translate.load('sbi.cockpit.table.threshold')}}

- +

@@ -162,11 +162,11 @@

- + - + @@ -189,7 +189,7 @@

- +

@@ -212,13 +212,13 @@

- + {{fs.label}} - + {{fs.label}} @@ -255,7 +255,7 @@

- +
{{::translate.load('sbi.cockpit.table.hidetooltip')}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnsGroup.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnsGroup.html index c8a47d5eac1..de8c301494c 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnsGroup.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-columns-configurator/templates/cockpitColumnsGroup.html @@ -15,7 +15,7 @@

Groups Management

No group defined
- +
{{group.name || 'New Group'}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/cockpitCrossConfigurator.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/cockpitCrossConfigurator.js index 5db360a7789..6f8c2533fcb 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/cockpitCrossConfigurator.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/cockpitCrossConfigurator.js @@ -126,13 +126,42 @@ function cockpitCrossConfiguratorControllerFunction($scope,sbiModule_translate,c } for(var i = 0; i < $scope.cockpitDatasets.length;i++){ - var meta = $scope.cockpitDatasets[i].metadata.fieldsMeta; - $scope.allCockpitDatasetsColumns[$scope.cockpitDatasets[i].label] = meta; + if($scope.cockpitDatasets[i].metadata && $scope.cockpitDatasets[i].metadata.fieldsMeta){ + var meta = $scope.cockpitDatasets[i].metadata.fieldsMeta; + $scope.allCockpitDatasetsColumns[$scope.cockpitDatasets[i].label] = meta; + } } $scope.getTemplateUrl = function(template){ return cockpitModule_generalServices.getTemplateUrl('tableWidget',template) } + + $scope.addLinkParameter = function(){ + if($scope.ngModel.link.parameters) $scope.ngModel.link.parameters.push({}); + else $scope.ngModel.link.parameters = [{}]; + } + + $scope.deleteLinkParameter = function(index){ + $scope.ngModel.link.parameters.splice(index,1); + } + + $scope.codemirrorLoaded = function(_editor) { + $scope._doc = _editor.getDoc(); + $scope._editor = _editor; + _editor.focus(); + $scope._doc.markClean() + _editor.on("beforeChange", function() {}); + _editor.on("change", function() {}); + }; + + //codemirror options + $scope.editorOptionsJSON = { + theme: 'eclipse', + lineWrapping: true, + lineNumbers: true, + mode: {name:"javascript"}, + onLoad: $scope.codemirrorLoaded + }; $scope.chooseIcon = function(type){ if($scope.iconOpened == type) $scope.iconOpened = false; @@ -230,29 +259,20 @@ function cockpitCrossConfiguratorControllerFunction($scope,sbiModule_translate,c $scope.crossText = $scope.localModel != undefined && $scope.localModel.type === 'text'; $scope.crossHtml = !$scope.localModel && $scope.$parent.newModel && $scope.$parent.newModel.type === 'html'; + + $scope.crossCustom = !$scope.localModel && $scope.$parent.newModel && $scope.$parent.newModel.type === 'customchart'; $scope.crossPython = !$scope.localModel && $scope.$parent.newModel && $scope.$parent.newModel.type === 'python'; $scope.crossImage = !$scope.localModel && !$scope.$parent.newModel; $scope.toggleEnabled = function(type){ - - if($scope.crossTable){ - if(type=='preview' && $scope.ngModel.cross && $scope.ngModel.cross.enable) { - $scope.$parent.newModel.cross.enable = $scope.ngModel.cross.enable = false; - } - if(type=='cross' && $scope.ngModel.preview && $scope.ngModel.preview.enable) { - $scope.$parent.newModel.preview.enable = $scope.ngModel.preview.enable = false; - } - }else{ - if(type=='preview' && $scope.ngModel.cross && $scope.ngModel.cross.enable) { - $scope.localModel.cross.enable = $scope.ngModel.cross.enable = false; - } - if(type=='cross' && $scope.ngModel.preview && $scope.ngModel.preview.enable) { - $scope.localModel.preview.enable = $scope.ngModel.preview.enable = false; - } + var toggleArray = ['cross','preview','link']; + if($scope.localModel) var crossModels = $scope.localModel; + if($scope.$parent && $scope.$parent.newModel) var crossModels = $scope.$parent.newModel.cross; + for(var k in toggleArray){ + if(toggleArray[k] != type && crossModels[toggleArray[k]]) crossModels[toggleArray[k]].enable = false; } - } $scope.$watchCollection('ngModel.preview.dataset',function(newValue,oldValue){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/template/cockpitCrossConfigurator.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/template/cockpitCrossConfigurator.html index 1e4a761f243..d9b8efaccce 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/template/cockpitCrossConfigurator.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-cross-configurator/template/cockpitCrossConfigurator.html @@ -5,7 +5,7 @@
{{::translate.load('kn.crossconfigurator.crossnavigation')}} - +
@@ -114,6 +114,7 @@ "> + {{::translate.load('sbi.cockpit.cross.outputParameter.selectedcolumnname')}} {{c.name}} @@ -191,7 +192,7 @@ {{::translate.load('kn.crossconfigurator.previewnavigation')}} - + @@ -209,10 +210,6 @@
- - @@ -283,7 +280,7 @@ - {{c.name}} + {{c.aliasToShow || c.name}} @@ -304,6 +301,135 @@
+ + Link + + + + + + + {{::translate.load('kn.crossconfigurator.interactiontype.wholerow')}} + {{::translate.load('kn.crossconfigurator.interactiontype.singlecolumn')}} + {{::translate.load('kn.crossconfigurator.interactiontype.icon')}} + + + +
+
+ {{::translate.load('kn.crossconfigurator.interactiontype.choose')}} +
+
+ + + + + + {{c.name}} + +
{{::translate.load('kn.crossconfigurator.hint.column')}}
+
+ + + + + + +
{{::translate.load('kn.crossconfigurator.link.baseurl.hint')}}
+
+ + + + + {{::translate.load('kn.crossconfigurator.link.type.samepage')}} + {{::translate.load('kn.crossconfigurator.link.type.blank')}} + + +
+ +
+ {{::translate.load('kn.crossconfigurator.link.urlparameters')}} + + {{::translate.load('sbi.cockpit.widget.table.summary.add')}} +
+
+ +
{{::translate.load('kn.crossconfigurator.link.noparameters')}}
+
+ +
+ + + + + + + + + + {{::translate.load('sbi.cockpit.cross.outputParameters.type.static')}} + {{::translate.load('sbi.cockpit.cross.outputParameters.type.dynamic')}} + {{::translate.load('kn.crossconfigurator.link.parameter.type.analyticaldriver')}} + {{::translate.load('kn.crossconfigurator.link.parameter.type.json')}} + {{::translate.load('sbi.cockpit.cross.outputParameters.type.selection')}} + {{::translate.load('sbi.cockpit.cross.parameter.type.jwt')}} + + + + + + + + + + + + + + {{::translate.load('sbi.cockpit.cross.outputParameter.selectedcolumnname')}} + {{c.name}} + + + + + + + + + {{val.label}} + + + + + + + + {{c.label}} + + + + + + {{c.name}} + + + + + + + + +
+ +
+ +
+

+ +

\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/cockpitDataConfigurationController.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/cockpitDataConfigurationController.js index a9f35dab8ad..d112df1890c 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/cockpitDataConfigurationController.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/cockpitDataConfigurationController.js @@ -32,7 +32,7 @@ function datasetManagerController($scope,sbiModule_translate,$mdPanel,cockpitMod } $scope.cockpitModule_analyticalDriversUrls = cockpitModule_analyticalDriversUrls; - + $scope.datasetTableActions=[{ label : 'delete', icon:'fa fa-trash' , @@ -642,16 +642,23 @@ function cockpitDataConfigurationController($scope,$rootScope,sbiModule_translat } }; -function variablesController($scope, sbiModule_translate, cockpitModule_template, cockpitModule_analyticalDrivers){ +function variablesController($scope, sbiModule_translate, cockpitModule_template, cockpitModule_analyticalDrivers,cockpitModule_analyticalDriversUrls){ $scope.variables = cockpitModule_template.configuration.variables; $scope.cockpitModule_template = cockpitModule_template; $scope.translate = sbiModule_translate; $scope.cockpitModule_analyticalDrivers = cockpitModule_analyticalDrivers; - - $scope.$watch('cockpitModule_template.configuration.datasets',function(newValue, oldValue){ - $scope.availableDatasets = newValue; - }) + + function getVariablesAnalyticalDrivers(){ + var tempVariablesAnalyticalDrivers = {}; + for(var k in cockpitModule_analyticalDriversUrls){ + var url = cockpitModule_analyticalDriversUrls[k].url; + tempVariablesAnalyticalDrivers[cockpitModule_analyticalDriversUrls[k].label] = url; + } + return tempVariablesAnalyticalDrivers; + } + + $scope.variablesAnalyticalDrivers = getVariablesAnalyticalDrivers(); $scope.availableColumns = function(id){ for(var k in $scope.tmpAvaiableDataset){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/templates/CockpitDataConfigurationVariables.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/templates/CockpitDataConfigurationVariables.html index a052225db70..e457cfa77ad 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/templates/CockpitDataConfigurationVariables.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-data-configuration/templates/CockpitDataConfigurationVariables.html @@ -39,14 +39,14 @@

{{::translate.load('kn.variables.definition')}}

- {{key}} + {{key}} - {{ds.name}} + {{ds.name}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-filters-configuration/cockpitFiltersConfiguration.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-filters-configuration/cockpitFiltersConfiguration.js index a38de7045a2..8c68285debb 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-filters-configuration/cockpitFiltersConfiguration.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-filters-configuration/cockpitFiltersConfiguration.js @@ -384,8 +384,13 @@ along with this program. If not, see . // TABLE CASE $scope.$watch("ngModelShared.dataset.dsId", function(newValue, oldValue) { if(newValue != undefined){ - $scope.refreshSingleDatasetCase(newValue, oldValue, 'table'); - $scope.cleanQbeColumns(); + if($scope.ngModelShared.type == 'text'){ + // new value is array containing all datasets currently included in widget + $scope.refreshMultiDatasetCase(newValue, 'text'); + }else { + $scope.refreshSingleDatasetCase(newValue, oldValue, 'table'); + $scope.cleanQbeColumns(); + } } }); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-general-configurator/templates/cockpitGeneralConfiguration.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-general-configurator/templates/cockpitGeneralConfiguration.html index bca87c456e1..134dfb5cb31 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-general-configurator/templates/cockpitGeneralConfiguration.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-general-configurator/templates/cockpitGeneralConfiguration.html @@ -76,6 +76,10 @@

General {{translate.load("sbi.cockpit.settings")}}

Enable screenshot functionality on widgets + + + Enable excel export functionality on widgets +

diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/cockpitSelectorConfigurator.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/cockpitSelectorConfigurator.js index 76ce45f2747..3af3bef81f2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/cockpitSelectorConfigurator.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/cockpitSelectorConfigurator.js @@ -38,6 +38,13 @@ $scope.setSelectorType = function(type){ $scope.model.settings.modalityValue = type; } + + if($scope.model.settings.defaultStartDate) $scope.model.settings.defaultStartDate = new Date($scope.model.settings.defaultStartDate); + if($scope.model.settings.defaultEndDate) $scope.model.settings.defaultEndDate = new Date($scope.model.settings.defaultEndDate); + $scope.setToDate = function(type){ + if(type == 'start') $scope.model.settings.defaultStartDate = new Date($scope.model.settings.defaultStartDate); + if(type == 'end') $scope.model.settings.defaultEndDate = new Date($scope.model.settings.defaultEndDate); + } $scope.showCircularcolumns = {value :false}; $scope.modalityValue = [ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/templates/cockpitSelectorConfiguratorTemplate.jsp b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/templates/cockpitSelectorConfiguratorTemplate.jsp index 90d0a4b93bf..451454d5b47 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/templates/cockpitSelectorConfiguratorTemplate.jsp +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-selector-configurator/templates/cockpitSelectorConfiguratorTemplate.jsp @@ -4,8 +4,8 @@ - - + + {{column.alias}} @@ -39,42 +39,55 @@
- {{::translate.load('sbi.cockpit.widgets.selector.selectordesignerpanel.selectoroptions.alignment')}} - - - - {{button.name}} - - - +
+ {{::translate.load('sbi.cockpit.widgets.selector.selectordesignerpanel.selectoroptions.alignment')}} + + + + {{button.name}} + + + +
{{::translate.load('sbi.cockpit.widgets.selector.selectordesignerpanel.selectoroptions.options')}} -
- - - - - {{v.name}} - - - - - - - - - - +
+ + + + + + + - - {{::translate.load('sbi.cockpit.widgets.selector.selectordesignerpanel.selectoroptions.wraptext')}} - - - {{::translate.load('kn.cockpit.selector.designer.hideDisabled')}} - - - {{::translate.load('kn.cockpit.selector.designer.enableAll')}} - +
+ +
+ + + + + {{v.name}} + + + + + + + + + + + + + {{::translate.load('sbi.cockpit.widgets.selector.selectordesignerpanel.selectoroptions.wraptext')}} + + + {{::translate.load('kn.cockpit.selector.designer.hideDisabled')}} + + + {{::translate.load('kn.cockpit.selector.designer.enableAll')}} +
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/cockpitStyleConfigurator.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/cockpitStyleConfigurator.js index 4181d9e56c9..716cad2f0b9 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/cockpitStyleConfigurator.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/cockpitStyleConfigurator.js @@ -168,6 +168,10 @@ function cockpitStyleConfiguratorControllerFunction($scope,sbiModule_translate,c $scope.changeShowScreenshot = function(){ $scope.ngModel.showScreenshot = !cockpitModule_template.configuration.showScreenshot; } + + $scope.changeShowExcelExport = function(){ + $scope.ngModel.showExcelExport = !cockpitModule_template.configuration.showExcelExport; + } $scope.bordersWatcher = $scope.$watch('ngModel.borders',function(newValue,oldValue){ $scope.borderColorOptions.disabled = !newValue; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/templates/cockpitStyleConfigurator.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/templates/cockpitStyleConfigurator.html index 70191864ccc..f2c8bc82fa8 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/templates/cockpitStyleConfigurator.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-style-configurator/templates/cockpitStyleConfigurator.html @@ -201,5 +201,7 @@

{{::translate.load("sbi.cockpit.style.options.other")}}

{{::translate.load("sbi.cockpit.style.options.enablescreenshot")}} {{::translate.load("sbi.cockpit.style.options.enablescreenshot")}} + + Enable show excel export(when available) \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/cockpitTextConfiguration.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/cockpitTextConfiguration.js index 3d99ce51362..de25dd6dfd1 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/cockpitTextConfiguration.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/cockpitTextConfiguration.js @@ -69,6 +69,7 @@ function cockpitTextControllerFunction($scope,cockpitModule_widgetServices, //set datasets references to ngModel $scope.datasetColumns=[]; $scope.ngModelShared.datasets = {}; + $scope.ngModelShared.clickFunctions = ['CROSS-NAVIGATION']; if ($scope.cockpitModule_template.configuration && $scope.cockpitModule_template.configuration.datasets){ for(var ds in $scope.cockpitModule_template.configuration.datasets){ // don't add all the datasets but only those who are selected by user @@ -81,7 +82,6 @@ function cockpitTextControllerFunction($scope,cockpitModule_widgetServices, $scope.ngModelShared.viewDatasetsDett[tmpDs.label] = false; $scope.ngModelShared.viewDatasets = true; $scope.ngModelShared.functions=['SUM', 'AVG', 'MIN', 'MAX','COUNT']; - $scope.ngModelShared.clickFunctions = ['CROSS-NAVIGATION']; } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/templates/cockpitTextConfiguration.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/templates/cockpitTextConfiguration.html index d9f4b960e2c..72d175401fb 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/templates/cockpitTextConfiguration.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-text-configuration/templates/cockpitTextConfiguration.html @@ -5,7 +5,7 @@

{{translate.load("sbi.cockpit.widgets.text.textWidgetDesigner.dynamic.title"

-
+
{{clickFunct}}
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/cockpitWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/cockpitWidget.js index af6c823ba32..7104b9e0c82 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/cockpitWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/cockpitWidget.js @@ -388,6 +388,12 @@ cockpitModule_templateServices.getDatasetUsetByWidgetWithParams(); return cockpitModule_template.configuration.showScreenshot; }else return $scope.ngModel.style.showScreenshot; } + + $scope.showExcelExportButton = function(){ + if(typeof($scope.ngModel.style.showExcelExport) == 'undefined' ) { + return cockpitModule_template.configuration.showExcelExport; + }else return $scope.ngModel.style.showExcelExport; + } $rootScope.$on('DELETE_SELECTION',function(event,data){ cockpitModule_widgetSelection.removeTimestampedSelection(data.ds,data.columnName); @@ -461,7 +467,14 @@ cockpitModule_templateServices.getDatasetUsetByWidgetWithParams(); } break; case "UPDATE_FROM_SHEET_CHANGE" : - $scope.refreshWidget(null,$scope.ngModel.type=="document" ? "parameter_change" : null); + var nature = null; + if($scope.ngModel.type=="document") { + nature = "parameter_change"; + } + if($scope.ngModel.type=="discovery") { + nature = "init"; + } + $scope.refreshWidget(null,nature); break; case "INIT" : $scope.scopeInit(config.element,config.width,config.height, config.data,config.nature,config.associativeSelection); @@ -780,7 +793,27 @@ cockpitModule_templateServices.getDatasetUsetByWidgetWithParams(); }).showToast(); } - $scope.doSelection = function(columnName, columnValue, modalColumn, modalValue, row, skipRefresh, dsId, disableAssociativeLogic){ + var replacePlaceholders = function(json, row){ + function adaptToType(value) { + return isNaN(value) ? '"'+value+'"' : value; + } + var jsonToReplace = json; + // variables + jsonToReplace = jsonToReplace.replace(/\$V\{([a-zA-Z0-9\_\-\.]+)\}/g, function(match,variable){ + return adaptToType(cockpitModule_properties.VARIABLES[variable]); + }); + // fields + jsonToReplace = jsonToReplace.replace(/\$F\{([a-zA-Z0-9\_\-\.]+)\}/g, function(match,field){ + return adaptToType(row[field]); + }); + // parameters + jsonToReplace = jsonToReplace.replace(/\$P\{([a-zA-Z0-9\_\-\.]+)\}/g, function(match,parameter){ + return adaptToType(cockpitModule_analyticalDrivers[parameter]); + }); + return JSON.stringify(JSON.parse(jsonToReplace)); + } + + $scope.doSelection = function(columnName, columnValue, modalColumn, modalValue, row, skipRefresh, dsId, disableAssociativeLogic,directInteraction){ if($scope.ngModel.cliccable==false){ console.log("widget is not cliccable") return; @@ -797,351 +830,415 @@ cockpitModule_templateServices.getDatasetUsetByWidgetWithParams(); var crossSettings; if($scope.ngModel.cross != undefined && $scope.ngModel.cross.cross != undefined) crossSettings = angular.copy($scope.ngModel.cross.cross); else if($scope.ngModel.cross != undefined) crossSettings = angular.copy($scope.ngModel.cross); - - - if (previewSettings && previewSettings.enable) { - if((previewSettings.previewType != 'singleColumn' || (previewSettings.previewType == 'singleColumn' && previewSettings.column == columnName)) && - (previewSettings.previewType != 'icon' || (previewSettings.previewType == 'icon' && columnName == ""))){ - $scope.iframeSrcUrl = sbiModule_config.host + sbiModule_config.externalBasePath + SERVICE; - - var previewDataset = cockpitModule_datasetServices.getDatasetById(previewSettings.dataset); - - var config = { - datasetLabel: previewDataset.label - }; - - if (previewDataset.parameters && previewDataset.parameters.length > 0) - config.parameters = $scope.checkPreviewParameters(previewSettings,previewDataset, columnName, modalColumn, row,columnValue); - - if(!previewSettings.background){ - //showing exporters - config.options = { - exports: ['CSV', 'XLSX'] + + var linkSettings; + if($scope.ngModel.cross != undefined && $scope.ngModel.cross.link != undefined) linkSettings = angular.copy($scope.ngModel.cross.link); + if($scope.ngModel.content && $scope.ngModel.content.link) linkSettings = angular.copy($scope.ngModel.content.link); + + if(!directInteraction || directInteraction == 'cross'){ + if (previewSettings && previewSettings.enable) { + if(previewSettings.previewType == 'allRow' || + (previewSettings.previewType == 'singleColumn' && previewSettings.column == columnName) || + (previewSettings.previewType == 'icon' && (!columnName || columnName == ""))){ + $scope.iframeSrcUrl = sbiModule_config.host + sbiModule_config.externalBasePath + SERVICE; + + var previewDataset = cockpitModule_datasetServices.getDatasetById(previewSettings.dataset); + + var config = { + datasetLabel: previewDataset.label }; - - $scope.iframeSrcUrl += '?' + $httpParamSerializer(config); - - $mdDialog.show({ - parent: angular.element(document.body), - templateUrl: currentScriptPath + '/widget/htmlWidget/templates/htmlWidgetPreviewDialogTemplate.html', - controller: function(scope) { - scope.previewUrl = $scope.iframeSrcUrl; - - scope.closePreview = function() { - $mdDialog.hide(); - } - }, - clickOutsideToClose: true - }).then(function(response){}, function(response){}); - }else{ - var id = previewDataset.id; - var data = {}; - if (config.parameters != null && typeof config.parameters != 'undefined') { - data.parameters = config.parameters; - }; - - $http.post(sbiModule_config.host + sbiModule_config.externalBasePath + PREVIEWBACKGROUND + id.dsId + '/csv', data) - .then( - function(response){ - popupMessage(response) - },function(error){ - popupMessage(error) - }); - } - return; - } - - }else if(crossSettings && crossSettings.enable){ - - // enter cross navigation mode - var doCross = false; - - var nameToCheckForCross = columnName; - if(columnName != undefined){ - // check if selected column has been renamed by an alias, in that - // case take the real name - for(var colIndex in model.content.columnSelectedOfDataset){ - var col = model.content.columnSelectedOfDataset[colIndex]; - if(col.aliasToShow != undefined && col.aliasToShow == columnName){ - nameToCheckForCross = col.name; - break; + + if (previewDataset.parameters && previewDataset.parameters.length > 0) + config.parameters = $scope.checkPreviewParameters(previewSettings,previewDataset, columnName, modalColumn, row,columnValue); + + if(!previewSettings.background){ + //showing exporters + config.options = { + exports: ['CSV', 'XLSX'] + }; + + $scope.iframeSrcUrl += '?' + $httpParamSerializer(config); + + $mdDialog.show({ + parent: angular.element(document.body), + templateUrl: currentScriptPath + '/widget/htmlWidget/templates/htmlWidgetPreviewDialogTemplate.html', + controller: function(scope) { + scope.previewUrl = $scope.iframeSrcUrl; + + scope.closePreview = function() { + $mdDialog.hide(); + } + }, + clickOutsideToClose: true + }).then(function(response){}, function(response){}); + }else{ + var id = previewDataset.id; + var data = {}; + if (config.parameters != null && typeof config.parameters != 'undefined') { + data.parameters = config.parameters; + }; + + $http.post(sbiModule_config.host + sbiModule_config.externalBasePath + PREVIEWBACKGROUND + id.dsId + '/csv', data) + .then( + function(response){ + popupMessage(response) + },function(error){ + popupMessage(error) + }); } + return; } - } - - if(crossSettings.crossType == "allRow" || crossSettings.crossType == "icon"){ - // case all columns are enabled for cross, get value for cross - // column (or alias if present) - var crossColumnOrAlias = crossSettings.column; - - for(var colIndex in model.content.columnSelectedOfDataset){ - var col = model.content.columnSelectedOfDataset[colIndex]; - if(col.aliasToShow != undefined && col.name == crossSettings.column){ - crossColumnOrAlias = col.aliasToShow; + + }else if(crossSettings && crossSettings.enable){ + + // enter cross navigation mode + var doCross = false; + var nameToCheckForCross = columnName; + if(columnName != undefined){ + // check if selected column has been renamed by an alias, in that + // case take the real name + for(var colIndex in model.content.columnSelectedOfDataset){ + var col = model.content.columnSelectedOfDataset[colIndex]; + if(col.aliasToShow != undefined && col.aliasToShow == columnName){ + nameToCheckForCross = col.name; + break; + } } } - if(crossSettings.crossType == "icon" && columnValue && crossSettings.column) doCross = false; - else doCross = true; - // get value to pass to cross navigation - if(row){ - if(row[crossColumnOrAlias]){ - columnValue = row[crossColumnOrAlias]; - }else{ - columnValue = []; - for(var j in row){ - columnValue.push(row[j][crossColumnOrAlias]); + + if(crossSettings.crossType == "allRow" || crossSettings.crossType == "icon"){ + // case all columns are enabled for cross, get value for cross + // column (or alias if present) + var crossColumnOrAlias = crossSettings.column; + + for(var colIndex in model.content.columnSelectedOfDataset){ + var col = model.content.columnSelectedOfDataset[colIndex]; + if(col.aliasToShow != undefined && col.name == crossSettings.column){ + crossColumnOrAlias = col.aliasToShow; + break; } } - } - }else if(model.type == 'static-pivot-table'){ - if(Array.isArray(columnName)) doCross = true; - }else{ - // case a specific column is enabled for cross - // check if column clicked is the one for cross navigation - if(crossSettings.column == undefined || crossSettings.column === nameToCheckForCross){ - doCross = true; - } - } + if(crossSettings.crossType == "icon" && columnValue && crossSettings.column) doCross = false; + else doCross = true; - if(doCross === true){ - var outputParameter = {}; - if(crossSettings.outputParameter){ - outputParameter[crossSettings.outputParameter] = columnValue; + }else if(model.type == 'static-pivot-table'){ + if(Array.isArray(columnName)) doCross = true; + }else{ + // case a specific column is enabled for cross + // check if column clicked is the one for cross navigation + if(crossSettings.column == undefined || crossSettings.column === nameToCheckForCross){ + doCross = true; + } } - - - // parse output parameters if enabled - var otherOutputParameters = []; - var passedOutputParametersList = crossSettings.outputParametersList; - - // get Aliases for column - var columnAliasesMap = {}; - if(model.content.columnSelectedOfDataset){ - for(var i = 0; i 1){ // sort keys - var temp = cockpitModule_template.configuration.filters[dsLabel]; - delete cockpitModule_template.configuration.filters[dsLabel]; - cockpitModule_template.configuration.filters[dsLabel] = temp; + //multiple selection: only from pivot table widget (by measure selection) + originalColumnName = []; + if ($scope.ngModel.content.crosstabDefinition){ + //check on pivot table structure: rows and columns definition + for (var k=0; k < columnName.length; k++){ + var singleColumnName = columnName[k]; + var foundInColumns = false; + var foundInRows = false; + for(var i=0; i<$scope.ngModel.content.crosstabDefinition.columns.length; i++){ + if(($scope.ngModel.content.crosstabDefinition.columns[i].alias && $scope.ngModel.content.crosstabDefinition.columns[i].alias.toUpperCase() === singleColumnName.toUpperCase()) || + $scope.ngModel.content.crosstabDefinition.columns[i].id.toUpperCase() === singleColumnName.toUpperCase()){ + originalColumnName.push($scope.ngModel.content.crosstabDefinition.columns[i].id); + foundInColumns = true; + break; + } + } + if (!foundInColumns){ + for(var i=0; i<$scope.ngModel.content.crosstabDefinition.rows.length; i++){ + if(($scope.ngModel.content.crosstabDefinition.rows[i].alias && $scope.ngModel.content.crosstabDefinition.rows[i].alias.toUpperCase() === singleColumnName.toUpperCase()) || + $scope.ngModel.content.crosstabDefinition.rows[i].id.toUpperCase() === singleColumnName.toUpperCase()){ + originalColumnName.push($scope.ngModel.content.crosstabDefinition.rows[i].id); + foundInRows = true; + break; + } + } + } + } + + // //at last sets the input columnName like the original name + if (!foundInColumns && !foundInRows){ + originalColumnName.push(singleColumnName); } } - if (Array.isArray(originalColumnName)){ - for (var o=0; o < originalColumnName.length; o++){ - var singleOriginalColumnValue = originalColumnName[o]; - if(cockpitModule_template.configuration.filters[dsLabel].hasOwnProperty(singleOriginalColumnValue)){ // sort keys - delete cockpitModule_template.configuration.filters[dsLabel][singleOriginalColumnValue]; + } + cockpitModule_widgetSelection.addTimestampedSelection(dsLabel, columnName, columnValue, $scope.ngModel.id); + var sel = disableAssociativeLogic ? "noAssoc" : cockpitModule_widgetSelection.getAssociativeSelections(columnValue,columnName,dsLabel,originalColumnName); + if(sel!=undefined){ + + + if(!cockpitModule_template.configuration.aliases){ + cockpitModule_template.configuration.aliases = []; + } + + if(!angular.equals("noAssoc",sel)){ + sel.then(function(response) { + if(!skipRefresh){ + cockpitModule_widgetSelection.refreshAllAssociatedWidget(false,response); } - cockpitModule_template.configuration.filters[dsLabel][singleOriginalColumnValue]=columnValue[o]; - cockpitModule_template.configuration.aliases.push({'dataset':dsLabel,'column':singleOriginalColumnValue,'alias':columnName[o]}); - } + }, function(error) { + console.log(error) + }); }else{ - if(cockpitModule_template.configuration.filters[dsLabel].hasOwnProperty(originalColumnName)){ // sort keys - delete cockpitModule_template.configuration.filters[dsLabel][originalColumnName]; + if(!cockpitModule_template.configuration.filters.hasOwnProperty(dsLabel)){ + cockpitModule_template.configuration.filters[dsLabel]={}; + } else{ + if(Object.keys(cockpitModule_template.configuration.filters).length > 1){ // sort keys + var temp = cockpitModule_template.configuration.filters[dsLabel]; + delete cockpitModule_template.configuration.filters[dsLabel]; + cockpitModule_template.configuration.filters[dsLabel] = temp; } - // 02/02/17 - davverna - // if columnvalue is an array, usually from a bulk selection, I use a copy to avoid the direct object binding. - // With the double click there is not the same issue because the binding is on a primitive value (string). - if(Object.prototype.toString.call( columnValue ) === '[object Array]'){ - cockpitModule_template.configuration.filters[dsLabel][originalColumnName]=[]; - angular.copy(columnValue,cockpitModule_template.configuration.filters[dsLabel][originalColumnName]); - }else{ - cockpitModule_template.configuration.filters[dsLabel][originalColumnName]=columnValue; + } + if (Array.isArray(originalColumnName)){ + for (var o=0; o < originalColumnName.length; o++){ + var singleOriginalColumnValue = originalColumnName[o]; + if(cockpitModule_template.configuration.filters[dsLabel].hasOwnProperty(singleOriginalColumnValue)){ // sort keys + delete cockpitModule_template.configuration.filters[dsLabel][singleOriginalColumnValue]; + } + cockpitModule_template.configuration.filters[dsLabel][singleOriginalColumnValue]=columnValue[o]; + cockpitModule_template.configuration.aliases.push({'dataset':dsLabel,'column':singleOriginalColumnValue,'alias':columnName[o]}); } - cockpitModule_template.configuration.aliases.push({'dataset':dsLabel,'column':originalColumnName,'alias':columnName}); - } - cockpitModule_properties.HAVE_SELECTIONS_OR_FILTERS=true; - - if(!skipRefresh){ - cockpitModule_widgetSelection.refreshAllWidgetWhithSameDataset(dsLabel); + }else{ + if(cockpitModule_template.configuration.filters[dsLabel].hasOwnProperty(originalColumnName)){ // sort keys + delete cockpitModule_template.configuration.filters[dsLabel][originalColumnName]; + } + // 02/02/17 - davverna + // if columnvalue is an array, usually from a bulk selection, I use a copy to avoid the direct object binding. + // With the double click there is not the same issue because the binding is on a primitive value (string). + if(Object.prototype.toString.call( columnValue ) === '[object Array]'){ + cockpitModule_template.configuration.filters[dsLabel][originalColumnName]=[]; + angular.copy(columnValue,cockpitModule_template.configuration.filters[dsLabel][originalColumnName]); + }else{ + cockpitModule_template.configuration.filters[dsLabel][originalColumnName]=columnValue; + } + cockpitModule_template.configuration.aliases.push({'dataset':dsLabel,'column':originalColumnName,'alias':columnName}); + } + cockpitModule_properties.HAVE_SELECTIONS_OR_FILTERS=true; + + if(!skipRefresh){ + cockpitModule_widgetSelection.refreshAllWidgetWhithSameDataset(dsLabel); + } + } - } } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/templates/cockpitWidget.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/templates/cockpitWidget.html index 5c579efd606..51bf41feb67 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/templates/cockpitWidget.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/templates/cockpitWidget.html @@ -57,12 +57,9 @@ - + {{::translate.load("sbi.cockpit.editor.widget.widgeteditorgenericconfpanel.search")}} - - - - + @@ -82,7 +79,7 @@ {{::translate.load("sbi.cockpit.editor.widget.widgeteditorgenericconfpanel.incomingeventsenabled.description")}} - + @@ -188,7 +185,7 @@ - + {{::translate.load("sbi.cockpit.widgets.tooltip.export")}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RMode.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RMode.js new file mode 100644 index 00000000000..be7db46b85a --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RMode.js @@ -0,0 +1,183 @@ +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: http://codemirror.net/LICENSE + +(function(mod) { + if (typeof exports == "object" && typeof module == "object") // CommonJS + mod(require("../../lib/codemirror")); + else if (typeof define == "function" && define.amd) // AMD + define(["../../lib/codemirror"], mod); + else // Plain browser env + mod(CodeMirror); +})(function(CodeMirror) { +"use strict"; + +CodeMirror.registerHelper("wordChars", "r", /[\w.]/); + +CodeMirror.defineMode("r", function(config) { + function wordObj(str) { + var words = str.split(" "), res = {}; + for (var i = 0; i < words.length; ++i) res[words[i]] = true; + return res; + } + var atoms = wordObj("NULL NA Inf NaN NA_integer_ NA_real_ NA_complex_ NA_character_"); + var builtins = wordObj("list quote bquote eval return call parse deparse"); + var keywords = wordObj("if else repeat while function for in next break"); + var blockkeywords = wordObj("if else repeat while function for"); + var opChars = /[+\-*\/^<>=!&|~$:]/; + var curPunc; + + function tokenBase(stream, state) { + curPunc = null; + var ch = stream.next(); + if (ch == "#") { + stream.skipToEnd(); + return "comment"; + } else if (ch == "0" && stream.eat("x")) { + stream.eatWhile(/[\da-f]/i); + return "number"; + } else if (ch == "." && stream.eat(/\d/)) { + stream.match(/\d*(?:e[+\-]?\d+)?/); + return "number"; + } else if (/\d/.test(ch)) { + stream.match(/\d*(?:\.\d+)?(?:e[+\-]\d+)?L?/); + return "number"; + } else if (ch == "'" || ch == '"') { + state.tokenize = tokenString(ch); + return "string"; + } else if (ch == "`") { + stream.match(/[^`]+`/); + return "variable-3"; + } else if (ch == "." && stream.match(/.[.\d]+/)) { + return "keyword"; + } else if (/[\w\.]/.test(ch) && ch != "_") { + stream.eatWhile(/[\w\.]/); + var word = stream.current(); + if (atoms.propertyIsEnumerable(word)) return "atom"; + if (keywords.propertyIsEnumerable(word)) { + // Block keywords start new blocks, except 'else if', which only starts + // one new block for the 'if', no block for the 'else'. + if (blockkeywords.propertyIsEnumerable(word) && + !stream.match(/\s*if(\s+|$)/, false)) + curPunc = "block"; + return "keyword"; + } + if (builtins.propertyIsEnumerable(word)) return "builtin"; + return "variable"; + } else if (ch == "%") { + if (stream.skipTo("%")) stream.next(); + return "operator variable-2"; + } else if ( + (ch == "<" && stream.eat("-")) || + (ch == "<" && stream.match("<-")) || + (ch == "-" && stream.match(/>>?/)) + ) { + return "operator arrow"; + } else if (ch == "=" && state.ctx.argList) { + return "arg-is"; + } else if (opChars.test(ch)) { + if (ch == "$") return "operator dollar"; + stream.eatWhile(opChars); + return "operator"; + } else if (/[\(\){}\[\];]/.test(ch)) { + curPunc = ch; + if (ch == ";") return "semi"; + return null; + } else { + return null; + } + } + + function tokenString(quote) { + return function(stream, state) { + if (stream.eat("\\")) { + var ch = stream.next(); + if (ch == "x") stream.match(/^[a-f0-9]{2}/i); + else if ((ch == "u" || ch == "U") && stream.eat("{") && stream.skipTo("}")) stream.next(); + else if (ch == "u") stream.match(/^[a-f0-9]{4}/i); + else if (ch == "U") stream.match(/^[a-f0-9]{8}/i); + else if (/[0-7]/.test(ch)) stream.match(/^[0-7]{1,2}/); + return "string-2"; + } else { + var next; + while ((next = stream.next()) != null) { + if (next == quote) { state.tokenize = tokenBase; break; } + if (next == "\\") { stream.backUp(1); break; } + } + return "string"; + } + }; + } + + var ALIGN_YES = 1, ALIGN_NO = 2, BRACELESS = 4 + + function push(state, type, stream) { + state.ctx = {type: type, + indent: state.indent, + flags: 0, + column: stream.column(), + prev: state.ctx}; + } + function setFlag(state, flag) { + var ctx = state.ctx + state.ctx = {type: ctx.type, + indent: ctx.indent, + flags: ctx.flags | flag, + column: ctx.column, + prev: ctx.prev} + } + function pop(state) { + state.indent = state.ctx.indent; + state.ctx = state.ctx.prev; + } + + return { + startState: function() { + return {tokenize: tokenBase, + ctx: {type: "top", + indent: -config.indentUnit, + flags: ALIGN_NO}, + indent: 0, + afterIdent: false}; + }, + + token: function(stream, state) { + if (stream.sol()) { + if ((state.ctx.flags & 3) == 0) state.ctx.flags |= ALIGN_NO + if (state.ctx.flags & BRACELESS) pop(state) + state.indent = stream.indentation(); + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + if (style != "comment" && (state.ctx.flags & ALIGN_NO) == 0) setFlag(state, ALIGN_YES) + + if ((curPunc == ";" || curPunc == "{" || curPunc == "}") && state.ctx.type == "block") pop(state); + if (curPunc == "{") push(state, "}", stream); + else if (curPunc == "(") { + push(state, ")", stream); + if (state.afterIdent) state.ctx.argList = true; + } + else if (curPunc == "[") push(state, "]", stream); + else if (curPunc == "block") push(state, "block", stream); + else if (curPunc == state.ctx.type) pop(state); + else if (state.ctx.type == "block" && style != "comment") setFlag(state, BRACELESS) + state.afterIdent = style == "variable" || style == "keyword"; + return style; + }, + + indent: function(state, textAfter) { + if (state.tokenize != tokenBase) return 0; + var firstChar = textAfter && textAfter.charAt(0), ctx = state.ctx, + closing = firstChar == ctx.type; + if (ctx.flags & BRACELESS) ctx = ctx.prev + if (ctx.type == "block") return ctx.indent + (firstChar == "{" ? 0 : config.indentUnit); + else if (ctx.flags & ALIGN_YES) return ctx.column + (closing ? 0 : 1); + else return ctx.indent + (closing ? 0 : config.indentUnit); + }, + + lineComment: "#" + }; +}); + +CodeMirror.defineMIME("text/x-rsrc", "r"); + +}); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RWidget.js new file mode 100644 index 00000000000..419d2ea0128 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/RWidget.js @@ -0,0 +1,237 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ + +/** + * @author Marco Balestri + */ + +(function () { + angular + .module('cockpitModule') + .config(function($locationProvider) { + $locationProvider.html5Mode(true); + }) + .directive('cockpitRWidget', function () { + return { + templateUrl: baseScriptPath+ '/directives/cockpit-widget/widget/RWidget/templates/RWidgetTemplate.html', + controller: cockpitRWidgetControllerFunction, + compile: function (tElement, tAttrs, transclude) { + return { + post: function postLink(scope, element, attrs, ctrl, transclud) { + element.ready(function () { + scope.initWidget(); + }); + } + }; + } + } + }) + + .directive('bindHtmlCompile', ['$compile', function ($compile) { + return { + restrict: 'A', + link: function (scope, element, attrs) { + scope.$watch(function () { + return scope.$eval(attrs.bindHtmlCompile); + }, function (value) { + element.html(value && value.toString()); + var compileScope = scope; + if (attrs.bindHtmlScope) { + compileScope = scope.$eval(attrs.bindHtmlScope); + } + $compile(element.contents())(compileScope); + }); + } + }; + }]) + + function cockpitRWidgetControllerFunction( + $scope, + $mdDialog, + $mdPanel, + $q, + $timeout, + $http, + $sce, + $location, + sbiModule_translate, + sbiModule_restServices, + sbiModule_config, + cockpitModule_properties, + cockpitModule_analyticalDrivers, + cockpitModule_generalServices, + cockpitModule_datasetServices, + cockpitModule_widgetSelection, + cockpitModule_template, + sbiModule_user) { + + $scope.getTemplateUrl = function (template) { + return cockpitModule_generalServices.getTemplateUrl('RWidget', template); + } + + $scope.refresh = function (element, width, height, datasetRecords, nature) { + $scope.showWidgetSpinner(); + if(nature == 'init') { + $timeout(function () { + $scope.widgetIsInit = true; + cockpitModule_properties.INITIALIZED_WIDGETS.push($scope.ngModel.id); + }, 500); + } + $scope.documentId = cockpitModule_properties.DOCUMENT_ID; + $scope.sendData(); + $scope.hideWidgetSpinner(); + } + + $scope.reinit = function() { + $scope.refreshWidget(); + } + + $scope.crossNavigation = function () { + $scope.doSelection(null, null, null, null, null, null, $scope.ngModel.dataset.dsId, null); + } + + $scope.buildAggregations = function (columnSelectedOfDataset, dataset_label) { + aggregations = {"measures": [], "categories": [], "dataset": dataset_label}; + for (i=0; i. + */ + +/** + * @author Marco Balestri + */ + +angular + .module('cockpitModule') + .controller('RWidgetEditControllerFunction', RWidgetEditControllerFunction) + +function RWidgetEditControllerFunction( + $scope, + $http, + $mdToast, + finishEdit, + model, + sbiModule_translate, + $mdDialog, + mdPanelRef, + cockpitModule_datasetServices, + cockpitModule_analyticalDrivers, + cockpitModule_helperDescriptors, + cockpitModule_generalOptions, + sbiModule_restServices) { + + $scope.translate = sbiModule_translate; + $scope.newModel = angular.copy(model); + $scope.formattedAnalyticalDrivers = []; + + $scope.setLibraries = function () { + sbiModule_restServices.restToRootProject(); + sbiModule_restServices.promiseGet('2.0/backendservices/widgets/RWidget/libraries', $scope.newModel.RAddress) + .then(function(response){ + $scope.newModel.libraries = []; + var librariesArray = JSON.parse((response.data.result)); + for (idx in librariesArray) { + lib = librariesArray[idx]; + name = lib[0]; + version = lib[1]; + $scope.newModel.libraries.push({"name": name, "version": version}) + } + }, function(error){ + }); + } + + sbiModule_restServices.restToRootProject(); + sbiModule_restServices.promiseGet('2.0/configs/category', 'R_CONFIGURATION') + .then(function(response){ + $scope.newModel.REnvs = $scope.buildEnvironments(response.data); + $scope.newModel.REnvsKeys = Object.keys($scope.newModel.REnvs); + }, function(error){ + }); + + for(var a in cockpitModule_analyticalDrivers){ + $scope.formattedAnalyticalDrivers.push({'name':a}); + } + + $scope.buildEnvironments = function (data) { + toReturn = {} + for (i=0; i '+params.value+''+params.value+'' : ''; + } + function isInputEditable(params) { + return typeof(params.data.name) !== 'undefined'; + } + function isAggregationEditable(params) { + if (params.data.isCalculated) return false; + return params.data.fieldType == "MEASURE" ? true : false; + } + + function aggregationRenderer(params) { + var aggregation = ' '+params.value+''; + if (!params.data.isCalculated && params.data.fieldType == "MEASURE") { + return aggregation; + } else return ""; + } + + function buttonRenderer(params){ + var calculator = ''; + if(params.data.isCalculated){ + calculator = ''; + } + return calculator + '{{::translate.load("sbi.cockpit.widgets.table.column.delete")}}'; + } + + function refreshRow(cell){ + $scope.columnsGrid.api.redrawRows({rowNodes: [$scope.columnsGrid.api.getDisplayedRowAtIndex(cell.rowIndex)]}); + } + + $scope.deleteColumn = function(rowName,event) { + for(var k in $scope.newModel.content.columnSelectedOfDataset){ + if($scope.newModel.content.columnSelectedOfDataset[k].name == rowName) var item = $scope.newModel.content.columnSelectedOfDataset[k]; + } + var index=$scope.newModel.content.columnSelectedOfDataset.indexOf(item); + $scope.newModel.content.columnSelectedOfDataset.splice(index,1); + } + + $scope.checkEnvironment = function(){ + if (!$scope.newModel.pythonAddress) return false; + else return true; + } + + $scope.checkDataset = function(){ + if (!$scope.newModel.dataset || !$scope.newModel.dataset.dsId) return false; + else return true; + } + + $scope.checkAliases = function(){ + var columns = $scope.newModel.content.columnSelectedOfDataset; + for(var i = 0; i < columns.length - 1; i++){ + for(var j = i + 1; j < columns.length; j++){ + if(columns[i].alias == columns[j].alias){ + return false; + } + } + } + return true; + } + + $scope.$watchCollection('newModel.content.columnSelectedOfDataset',function(newValue,oldValue){ + if($scope.columnsGrid.api && newValue){ + $scope.columnsGrid.api.setRowData(newValue); + $scope.columnsGrid.api.sizeColumnsToFit(); + } + }) + + $scope.openListColumn = function(){ + if($scope.newModel.dataset == undefined || $scope.newModel.dataset.dsId == undefined){ + $scope.showAction($scope.translate.load("sbi.cockpit.table.missingdataset")); + }else{ + $mdDialog.show({ + templateUrl: baseScriptPath+ '/directives/cockpit-columns-configurator/templates/cockpitColumnsOfDataset.html', + parent : angular.element(document.body), + clickOutsideToClose:true, + escapeToClose :true, + preserveScope: true, + autoWrap:false, + locals: {model:$scope.newModel, getMetadata : $scope.getMetadata}, + fullscreen: true, + controller: addColumnController + }).then(function(returnModel) { + $scope.newModel.content.columnSelectedOfDataset = returnModel; + }, function() { + }); + } + } + + $scope.showAction = function(text) { + var toast = $mdToast.simple() + .content(text) + .action('OK') + .highlightAction(false) + .hideDelay(3000) + .position('top') + + $mdToast.show(toast).then(function(response) { + + if ( response == 'ok' ) { + + + } + }); + } + +} + + +function addColumnController($scope,sbiModule_translate,$mdDialog,model,getMetadata,cockpitModule_datasetServices,cockpitModule_generalOptions){ + $scope.translate=sbiModule_translate; + $scope.model = angular.copy(model); + $scope.columnSelected = []; + $scope.localDataset = {}; + if($scope.model.dataset && $scope.model.dataset.dsId){ + angular.copy(cockpitModule_datasetServices.getDatasetById($scope.model.dataset.dsId), $scope.localDataset); + } else{ + $scope.model.dataset= {}; + angular.copy([], $scope.model.dataset.metadata.fieldsMeta); + } + + $scope.filterColumns = function(){ + var tempColumnsList = $filter('filter')($scope.localDataset.metadata.fieldsMeta,$scope.columnsSearchText); + $scope.columnsGridOptions.api.setRowData(tempColumnsList); + } + + $scope.columnsGridOptions = { + enableColResize: false, + enableFilter: true, + enableSorting: true, + pagination: true, + paginationAutoPageSize: true, + onGridSizeChanged: resizeColumns, + rowSelection: 'multiple', + rowMultiSelectWithClick: true, + defaultColDef: { + suppressMovable: true, + tooltip: function (params) { + return params.value; + }, + }, + columnDefs :[{"headerName":"Column","field":"alias",headerCheckboxSelection: true, checkboxSelection: true}, + {"headerName":"Field Type","field":"fieldType"}, + {"headerName":"Type","field":"type"}], + rowData : $scope.localDataset.metadata.fieldsMeta + }; + + function resizeColumns(){ + $scope.columnsGridOptions.api.sizeColumnsToFit(); + } + + $scope.saveColumnConfiguration=function(){ + if($scope.model.content.columnSelectedOfDataset == undefined){ + $scope.model.content.columnSelectedOfDataset = []; + } + + for(var i in $scope.columnsGridOptions.api.getSelectedRows()){ + var obj = $scope.columnsGridOptions.api.getSelectedRows()[i]; + obj.aggregationSelected = 'SUM'; + obj.typeSelected = obj.type; + $scope.model.content.columnSelectedOfDataset.push(obj); + } + $mdDialog.hide($scope.model.content.columnSelectedOfDataset); + } + + $scope.cancelConfiguration=function(){ + $mdDialog.cancel(); + } + +} + diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetEditPropertyTemplate.html new file mode 100644 index 00000000000..8400cb8f4fc --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetEditPropertyTemplate.html @@ -0,0 +1,170 @@ + + + +
+

{{translate.load('kn.cockpit.R.configuration')}}

+ +
+
+ + + + + + + + + + + + + + + +
+ {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.tablecolumns')}} + + {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.addcolumn')}} + +
+
+
+ +
+
+
+
+
+ + + + + + +
+ + + + + + + {{key}} + + + + + + + + + + + + + + + +
+

{{translate.load('kn.cockpit.R.RScript')}}

+ +
+
+ + + +
+
+
+ +

{{translate.load('kn.cockpit.R.availabletags')}}

+
+ {{tag.label}} +
+

+ {{tag.description}} +

+
{{tag.hiddenMessage}}
+
+ + + + {{opt.name}} + + + + + {{input.label || input.name}} + +
+
+ + Insert + +
+
+ +
+
+ +
+ + + + + + + + + + + {{key}} + + + + + + + + + + + + + + + + + + + + + + +
{{translate.load('sbi.cockpit.widget.R.library')}}{{translate.load('sbi.cockpit.widget.R.version')}}
{{lib.name}}{{lib.version}}
+ +
+
+
+ + + + + + + + + + + +
+
+
+ + + {{translate.load('sbi.generic.cancel')}} + + + {{translate.load('sbi.generic.save')}} + + +
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetTemplate.html new file mode 100644 index 00000000000..039a36b5ff7 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/RWidget/templates/RWidgetTemplate.html @@ -0,0 +1 @@ +
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidget.js index 6f849279a0f..4c0424aae30 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidget.js @@ -66,6 +66,7 @@ along with this program. If not, see . function escapeIfString(value){ if(typeof value != 'number') return "\""+value+"\""; + else return value; } var _rowHeight; @@ -79,6 +80,11 @@ along with this program. If not, see . if(!$scope.ngModel.style) $scope.ngModel.style = cockpitModule_defaultTheme.table.style; function getColumns(fields,sortedDefault) { var crossEnabled = $scope.ngModel.cross && $scope.ngModel.cross.cross && $scope.ngModel.cross.cross.enable; + if($scope.ngModel.cross) { + for(var c in $scope.ngModel.cross){ + if($scope.ngModel.cross[c].enable) $scope.interaction = angular.copy($scope.ngModel.cross[c]); + } + } var columns = []; $scope.columnsNameArray = []; @@ -86,12 +92,18 @@ along with this program. If not, see . var columnGroups = {}; for(var c in $scope.ngModel.content.columnSelectedOfDataset){ for(var f in fields){ - if(typeof fields[f] == 'object' && (dataset.type == "SbiSolrDataSet" && $scope.ngModel.content.columnSelectedOfDataset[c].name === fields[f].header || $scope.ngModel.content.columnSelectedOfDataset[c].aliasToShow === fields[f].header) ){ + var thisColumn = $scope.ngModel.content.columnSelectedOfDataset[c]; + if(typeof fields[f] == 'object' && (dataset.type == "SbiSolrDataSet" && thisColumn.name.toLowerCase() === fields[f].header || ((thisColumn.aliasToShow || thisColumn.alias).toLowerCase() === fields[f].header.toLowerCase())) ){ $scope.columnsNameArray.push(fields[f].name); var tempCol = {"headerName":$scope.ngModel.content.columnSelectedOfDataset[c].aliasToShow || $scope.ngModel.content.columnSelectedOfDataset[c].alias, "field":fields[f].name,"measure":$scope.ngModel.content.columnSelectedOfDataset[c].fieldType}; tempCol.headerTooltip = $scope.ngModel.content.columnSelectedOfDataset[c].aliasToShow || $scope.ngModel.content.columnSelectedOfDataset[c].alias; tempCol.pinned = $scope.ngModel.content.columnSelectedOfDataset[c].pinned; + + if ($scope.ngModel.content.columnSelectedOfDataset[c].isCalculated){ + tempCol.isCalculated = $scope.ngModel.content.columnSelectedOfDataset[c].isCalculated; + } + if(sortedDefault && sortedDefault[0].colId == fields[f].name){ tempCol.sort = sortedDefault[0].sort; } @@ -116,7 +128,7 @@ along with this program. If not, see . for(var k in $scope.ngModel.content.columnSelectedOfDataset[c].variables){ var variableUsage = $scope.ngModel.content.columnSelectedOfDataset[c].variables[k]; var variableValue = cockpitModule_properties.VARIABLES[variableUsage.variable]; - if(typeof cockpitModule_properties.VARIABLES[variableUsage.variable] == 'object' && cockpitModule_properties.VARIABLES[variableUsage.variable][variableUsage.key]) { + if(typeof cockpitModule_properties.VARIABLES[variableUsage.variable] == 'object' && typeof cockpitModule_properties.VARIABLES[variableUsage.variable][variableUsage.key] != 'undefined') { variableValue = cockpitModule_properties.VARIABLES[variableUsage.variable][variableUsage.key]; } if(variableUsage.action == 'hide' && eval(escapeIfString(variableValue) + variableUsage.condition + escapeIfString(variableUsage.value))) tempCol.hide = true; @@ -130,7 +142,7 @@ along with this program. If not, see . if(!$scope.ngModel.content.columnSelectedOfDataset[c].hideTooltip) { tempCol.tooltipValueGetter = TooltipValue; } - if(crossEnabled && $scope.ngModel.cross.cross.crossType == 'singleColumn' && $scope.ngModel.cross.cross.column == $scope.ngModel.content.columnSelectedOfDataset[c].aliasToShow) { + if($scope.interaction && $scope.interaction.column == $scope.ngModel.content.columnSelectedOfDataset[c].name && ($scope.interaction.crossType == 'singleColumn' || $scope.interaction.interactionType == 'singleColumn')) { tempCol.cellClass = 'cross-cell'; delete tempCol.tooltipField; tempCol.tooltipValueGetter = function(params) { @@ -186,11 +198,12 @@ along with this program. If not, see . //Columns group managament if($scope.ngModel.content.columnSelectedOfDataset[c].group && $scope.ngModel.groups && $scope.ngModel.groups.length > 0) { $scope.ngModel.groups.forEach(function(group){ - if(group.name == $scope.ngModel.content.columnSelectedOfDataset[c].group){ - if(columnGroups[group.name]) { - columns[columnGroups[group.name]].children.push(tempCol); + var groupKey = group.id ? group.id : group.name; + if(groupKey == $scope.ngModel.content.columnSelectedOfDataset[c].group){ + if(typeof columnGroups[groupKey] != 'undefined') { + columns[columnGroups[groupKey]].children.push(tempCol); }else { - columnGroups[group.name] = columns.length; + columnGroups[groupKey] = columns.length; columns.push({ headerName: group.name, headerGroupComponent: CustomHeaderGroupRenderer, @@ -206,9 +219,9 @@ along with this program. If not, see . } } } - if((crossEnabled && $scope.ngModel.cross.cross.crossType == "icon") || ($scope.ngModel.cross.preview && $scope.ngModel.cross.preview.enable && $scope.ngModel.cross.preview.previewType == "icon")){ + if($scope.interaction && ($scope.interaction.crossType == "icon" || $scope.interaction.previewType == "icon" || $scope.interaction.interactionType == "icon")){ columns.push({headerName:"",field:(crossEnabled && $scope.ngModel.cross.cross.column) || "", - crossIcon: (crossEnabled && $scope.ngModel.cross.cross.icon) || ($scope.ngModel.cross.preview && $scope.ngModel.cross.preview.enable && $scope.ngModel.cross.preview.icon), + crossIcon: $scope.interaction.icon, cellRenderer:crossIconRenderer,"cellStyle":{"text-align": "right","display":"inline-flex","justify-content":"center","border":"none"}, sortable:false,filter:false,width: 50,suppressSizeToFit:true, tooltipValueGetter: false}); } @@ -248,6 +261,7 @@ along with this program. If not, see . var properties = ["justify-content","color","background-color","font-style","font-weight","font-size"]; properties.forEach(function(property){ if(!headerStyle[property] && params.column.colDef.style[property]) headerStyle[property] = params.column.colDef.style[property]; + if(property == "justify-content" && headerStyle[property] && params.column.colDef.style[property]) headerStyle[property] = params.column.colDef.style[property]; }) } this.eGui = document.createElement('div'); @@ -331,8 +345,13 @@ along with this program. If not, see . return isNaN(moment(params.value,'DD/MM/YYYY HH:mm:ss.SSS'))? params.value : moment(params.value,'DD/MM/YYYY HH:mm:ss.SSS').locale(sbiModule_config.curr_language).format(params.colDef.dateFormat || 'LLL'); } + /* + * The number formatter prepares the data to show the number correctly in the user locale format. + * If a precision is set will use it, otherwise will set the precision to 2 if float, 0 if int. + * In case of a returning empty string that one will be displayed. + */ function numberFormatter(params){ - if(params.value != "" && !params.colDef.style || (params.colDef.style && !params.colDef.style.asString)) { + if(params.value != "" && (!params.colDef.style || (params.colDef.style && !params.colDef.style.asString))) { var defaultPrecision = (params.colDef.fieldType == 'float') ? 2 : 0; return $filter('number')(params.value, (params.colDef.style && typeof params.colDef.style.precision != 'undefined') ? params.colDef.style.precision : defaultPrecision); }else return params.value; @@ -394,7 +413,11 @@ along with this program. If not, see . tempValue = tempValue.toString().substring(0,params.colDef.style.maxChars); } } - if(this.eGui.innerHTML == '') this.eGui.innerHTML = ((params.colDef.style && params.colDef.style.prefix) || '') + tempValue + ((params.colDef.style && params.colDef.style.suffix) || ''); + params.eParentOfValue.style.backgroundColor = (params.colDef.style && params.colDef.style['background-color']) || 'inherit'; + if($scope.bulkSelection){ + this.manageMultiSelection(params); + } + if(typeof tempValue != "undefined" && this.eGui.innerHTML == '') this.eGui.innerHTML = ((params.colDef.style && params.colDef.style.prefix) || '') + tempValue + ((params.colDef.style && params.colDef.style.suffix) || ''); } cellRenderer.prototype.getGui = function() { @@ -402,13 +425,21 @@ along with this program. If not, see . }; cellRenderer.prototype.refresh = function(params) { - this.eGui.parentNode.style.backgroundColor = params.colDef.style && params.colDef.style['background-color'] || 'inherit'; if($scope.bulkSelection){ - if($scope.ngModel.cross && $scope.ngModel.cross.cross && $scope.ngModel.cross.cross.enable && $scope.ngModel.cross.cross.crossType == 'allRow'){ - if($scope.selectedCells.indexOf(params.data[$scope.bulkSelection]) > -1) this.eGui.parentNode.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; - }else if(params.colDef.field == $scope.bulkSelection && $scope.selectedCells.indexOf(params.value) > -1){ - this.eGui.parentNode.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; + this.manageMultiSelection(params); + } + } + + cellRenderer.prototype.manageMultiSelection = function(params) { + params.eParentOfValue.style.backgroundColor = (params.colDef.style && params.colDef.style['background-color']) || 'inherit'; + if($scope.interaction && ($scope.interaction.crossType == 'allRow' || $scope.interaction.interactionType == 'allRow')){ + if($scope.selectedCells.indexOf(params.data[$scope.bulkSelection]) > -1) { + if(this.eGui.parentNode) this.eGui.parentNode.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; + else params.eParentOfValue.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; } + }else if(params.colDef.field == $scope.bulkSelection && $scope.selectedCells.indexOf(params.value) > -1){ + if(this.eGui.parentNode) this.eGui.parentNode.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; + else params.eParentOfValue.style.backgroundColor = $scope.ngModel.settings.multiselectablecolor || '#ccc'; } } @@ -453,13 +484,15 @@ along with this program. If not, see . if(params.colDef.style && params.colDef.style.hideSummary) this.eGui.innerHTML = ''; else { var title = params.summaryRows[params.rowIndex].label; - if(title && params.style && params.style['pinnedOnly'] && params.column.pinned && params.column.lastLeftPinned) this.eGui.innerHTML =''+title+''; + if(title && params.style && params.style['pinnedOnly'] && params.column.pinned) this.eGui.innerHTML =''+title+''; if(params.valueFormatted || params.value){ - if(params.summaryRows[params.rowIndex].aggregation == 'COUNT' || params.summaryRows[params.rowIndex].aggregation == 'COUNT_DISTINCT') { - var tempValue = $filter('number')(params.value,0); - }else var tempValue = params.valueFormatted || params.value; - if((!params.style || !params.style['pinnedOnly']) && title) this.eGui.innerHTML =''+title+''; - this.eGui.innerHTML += tempValue; + if (params.rowIndex == 0 || !params.colDef.isCalculated) { + if(params.summaryRows[params.rowIndex].aggregation == 'COUNT' || params.summaryRows[params.rowIndex].aggregation == 'COUNT_DISTINCT') { + var tempValue = $filter('number')(params.value,0); + }else var tempValue = params.valueFormatted || params.value; + if((!params.style || !params.style['pinnedOnly']) && title) this.eGui.innerHTML =''+title+''; + this.eGui.innerHTML += tempValue; + } } } }; @@ -514,7 +547,10 @@ along with this program. If not, see . if($scope.ngModel.style && $scope.ngModel.style.tr && $scope.ngModel.style.tr.height){ _rowHeight = $scope.ngModel.style.tr.height; $scope.advancedTableGrid.api.resetRowHeights(); - }else delete _rowHeight; + }else { + _rowHeight = 0; + $scope.advancedTableGrid.api.resetRowHeights(); + } if($scope.ngModel.style && $scope.ngModel.style.th){ if($scope.ngModel.style.th.enabled) $scope.advancedTableGrid.api.setHeaderHeight($scope.ngModel.style.th.height || 32); else $scope.advancedTableGrid.api.setHeaderHeight(0); @@ -585,10 +621,7 @@ along with this program. If not, see . agColumnHeader: CustomHeader }, onColumnResized: columnResized, - getRowHeight: function(params){ - if(_rowHeight > 0) return parseInt(_rowHeight); - else return 28; - }, + getRowHeight: getRowHeight, getRowStyle: function(params) { // TODO : make this a CSS rule with a custom class if($scope.ngModel.settings.alternateRows && $scope.ngModel.settings.alternateRows.enabled){ @@ -604,6 +637,7 @@ along with this program. If not, see . } if($scope.ngModel.settings.norows && $scope.ngModel.settings.norows.message) $scope.advancedTableGrid.localeText.noRowsToShow = $scope.ngModel.settings.norows.message; + function getRowHeight(params) { if(_rowHeight > 0) return _rowHeight; else return 28; @@ -612,7 +646,7 @@ along with this program. If not, see . if($scope.ngModel.settings.pagination && $scope.ngModel.settings.pagination.enabled && !$scope.ngModel.settings.pagination.frontEnd){ $scope.showWidgetSpinner(); var sorting = $scope.advancedTableGrid.api.getSortModel(); - sorting[0].colId = sorting[0].colId.replace(/(column_[0-9]+)(?:_[0-9]+)/gm, '$1'); + if(sorting[0]) sorting[0].colId = sorting[0].colId.replace(/(column_[0-9]+)(?:_[0-9]+)/gm, '$1'); $scope.ngModel.settings.sortingColumn = sorting.length>0 ? getColumnName(sorting[0].colId) : ''; $scope.ngModel.settings.sortingOrder = sorting.length>0 ? sorting[0]['sort'].toUpperCase() : ''; $scope.refreshWidget(null, 'sorting'); @@ -705,27 +739,29 @@ along with this program. If not, see . } } - function getColumnNameFromTableMetadata(colAlias){ + function getColumnNameFromTableMetadata(colAlias, colId){ + if(colId){ + for(var m in $scope.metadata.fields){ + if($scope.metadata.fields[m].name && $scope.metadata.fields[m].name == colId) return $scope.metadata.fields[m].header; + } + } for(var k in $scope.ngModel.content.columnSelectedOfDataset){ if($scope.ngModel.content.columnSelectedOfDataset[k].aliasToShow && $scope.ngModel.content.columnSelectedOfDataset[k].aliasToShow == colAlias) return $scope.ngModel.content.columnSelectedOfDataset[k].name; } } function onCellClicked(node){ - var allRowEnabled = $scope.ngModel.cross && $scope.ngModel.cross.cross && $scope.ngModel.cross.cross.enable && $scope.ngModel.cross.cross.crossType == 'allRow'; - var allRowEnabledPreview = $scope.ngModel.cross && $scope.ngModel.cross.preview && $scope.ngModel.cross.preview.enable && $scope.ngModel.cross.preview.previewType == 'allRow'; - var iconEnabled = $scope.ngModel.cross && $scope.ngModel.cross.cross && $scope.ngModel.cross.cross.enable && $scope.ngModel.cross.cross.crossType == 'icon'; - var previewIconEnabled = $scope.ngModel.cross && $scope.ngModel.cross.preview && $scope.ngModel.cross.preview.enable && $scope.ngModel.cross.preview.previewType == 'icon'; + var interactionType = $scope.interaction && ($scope.interaction.crossType || $scope.interaction.previewType || $scope.interaction.interactionType); if($scope.cliccable==false) return; - if(node.colDef.measure=='MEASURE' && !$scope.ngModel.settings.modalSelectionColumn && !allRowEnabled && !allRowEnabledPreview) return; - if(!previewIconEnabled && !iconEnabled && (node.value == "" || node.value == undefined)) return; + if(node.colDef.measure=='MEASURE' && !$scope.ngModel.settings.modalSelectionColumn && interactionType != 'allRow') return; + if(interactionType != "icon" && (node.value == "" || node.value == undefined)) return; if(node.rowPinned) return; - if(iconEnabled && node.colDef.crossIcon) { + if(interactionType == "icon" && node.colDef.crossIcon) { $scope.doSelection(node.colDef.field || null, null, null, null, mapRow(node.data)); return; } - if ($scope.ngModel.cross && $scope.ngModel.cross.preview && $scope.ngModel.cross.preview.enable) { - switch ($scope.ngModel.cross.preview.previewType) { + if ($scope.interaction && $scope.interaction.previewType && $scope.interaction.enable) { + switch (interactionType) { case 'allRow': previewDataset(mapRow(node.data), node.colDef.headerName); return; @@ -747,12 +783,12 @@ along with this program. If not, see . if($scope.ngModel.settings.multiselectable) { //first check to see it the column selected is the same, if not clear the past selections - if(!$scope.bulkSelection || ($scope.bulkSelection!=node.colDef.field && !allRowEnabled)){ + if(!$scope.bulkSelection || ($scope.bulkSelection!=node.colDef.field && interactionType != 'allRow')){ $scope.selectedCells.splice(0,$scope.selectedCells.length); $scope.selectedRows.splice(0,$scope.selectedRows.length); - if($scope.ngModel.cross && allRowEnabled){ + if($scope.interaction && interactionType == 'allRow'){ for(var f in $scope.metadata.fields){ - if($scope.metadata.fields[f].header && $scope.metadata.fields[f].header == $scope.ngModel.cross.cross.column){ + if($scope.metadata.fields[f].header && $scope.metadata.fields[f].header == $scope.interaction.column){ $scope.bulkSelection = $scope.metadata.fields[f].name; break; } @@ -760,7 +796,7 @@ along with this program. If not, see . }else $scope.bulkSelection = node.colDef.field; $scope.$apply(); } - if($scope.ngModel.cross && allRowEnabled){ + if($scope.interaction && interactionType == 'allRow'){ if(($scope.selectedCells.indexOf(node.data[$scope.bulkSelection])==-1)){ $scope.selectedCells.push(node.data[$scope.bulkSelection]); $scope.selectedRows.push(node.data); @@ -797,7 +833,7 @@ along with this program. If not, see . else { newValue = null; } - $scope.doSelection(getColumnNameFromTableMetadata(node.colDef.headerName), node.value, $scope.ngModel.settings.modalSelectionColumn, newValue, mapRow(node.data)); + $scope.doSelection(getColumnNameFromTableMetadata(node.colDef.headerName, node.colDef.field), node.value, $scope.ngModel.settings.modalSelectionColumn, newValue, mapRow(node.data)); } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidgetEdit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidgetEdit.js index 603ad2fc1e4..f56db08cdd2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidgetEdit.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/advancedTableWidgetEdit.js @@ -16,12 +16,12 @@ angular .module('cockpitModule') .controller('advancedTableWidgetEditControllerFunction',advancedTableWidgetEditControllerFunction) -function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q,model,sbiModule_translate,$mdDialog,mdPanelRef,$mdToast,cockpitModule_datasetServices,cockpitModule_generalOptions, cockpitModule_analyticalDrivers){ +function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q,model,sbiModule_translate,$mdDialog,mdPanelRef,$mdToast,cockpitModule_datasetServices,cockpitModule_generalOptions, cockpitModule_analyticalDrivers, sbiModule_restServices,cockpitModule_template){ $scope.translate=sbiModule_translate; $scope.newModel = angular.copy(model); $scope.cockpitModule_generalOptions = cockpitModule_generalOptions; $scope.availableAggregations = ["NONE","SUM","AVG","MAX","MIN","COUNT","COUNT_DISTINCT"]; - $scope.availableSummaryAggregations = ["NONE","SUM","AVG","COUNT","COUNT_DISTINCT"]; + $scope.availableSummaryAggregations = ["SUM","AVG","COUNT","COUNT_DISTINCT", "MAX", "MIN"]; $scope.typesMap = cockpitModule_generalOptions.typesMap; $scope.allHidden = false; for(var k in $scope.newModel.content.columnSelectedOfDataset){ @@ -31,6 +31,13 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q break; } } + + function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } $scope.changeDS = function(id){ $scope.newModel.content.columnSelectedOfDataset = cockpitModule_datasetServices.getDatasetById(id).metadata.fieldsMeta; @@ -39,8 +46,27 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q if($scope.newModel.content.columnSelectedOfDataset[c].fieldType == 'MEASURE' && !$scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected) $scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected = 'SUM'; if($scope.newModel.content.columnSelectedOfDataset[c].fieldType == 'MEASURE' && !$scope.newModel.content.columnSelectedOfDataset[c].funcSummary) $scope.newModel.content.columnSelectedOfDataset[c].funcSummary = $scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected; } + $scope.getDatasetAdditionalInfo(id); $scope.columnsGrid.api.setRowData($scope.newModel.content.columnSelectedOfDataset); } + + $scope.getDatasetAdditionalInfo = function(dsId){ + for(var k in cockpitModule_template.configuration.datasets){ + if(cockpitModule_template.configuration.datasets[k].dsId == dsId) { + $scope.localDataset = cockpitModule_template.configuration.datasets[k]; + break; + } + + } + sbiModule_restServices.restToRootProject(); + sbiModule_restServices.promiseGet('2.0/datasets', 'availableFunctions/' + dsId, "useCache=" + $scope.localDataset.useCache).then(function(response){ + $scope.datasetAdditionalInfos = response.data; + }, function(response) { + if(response.data && response.data.errors && response.data.errors[0]) $scope.showAction(response.data.errors[0].message); + else $scope.showAction($scope.translate.load('sbi.generic.error')); + }); + } + if($scope.newModel.dataset && $scope.newModel.dataset.dsId) $scope.getDatasetAdditionalInfo($scope.newModel.dataset.dsId); function moveInArray(arr, fromIndex, toIndex) { var element = arr[fromIndex]; @@ -49,9 +75,10 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q } function getColumnsDefinition() { - $scope.availableGroups = ['']; + $scope.availableGroups = {0:''}; for(var g in $scope.newModel.groups){ - $scope.availableGroups.push($scope.newModel.groups[g].name); + if(!$scope.newModel.groups[g].id) $scope.newModel.groups[g].id = uuidv4(); + $scope.availableGroups[$scope.newModel.groups[g].id] = $scope.newModel.groups[g].name; } $scope.columnsDefinition = [ @@ -65,7 +92,8 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q headerComponent: CustomHeader,headerClass:'header-cell-buttons'}]; if($scope.newModel.groups && $scope.newModel.groups.length > 0){ delete $scope.columnsDefinition[0].rowDrag; - $scope.columnsDefinition.unshift({headerName: 'Group', field:'group',"editable":isInputEditable,cellRenderer:groupRenderer, cellClass: 'editableCell',rowDrag: true,cellEditor:"agSelectCellEditor",cellEditorParams: {values: $scope.availableGroups}}); + $scope.columnsDefinition.unshift({headerName: 'Group', field:'group',"editable":isInputEditable,cellRenderer:groupRenderer, cellClass: 'editableCell',rowDrag: true,cellEditor:"agSelectCellEditor", + cellEditorParams: {values: Object.keys($scope.availableGroups)},valueFormatter: groupSelectFormatter, valueParser: groupSelectParser}); } if($scope.columnsGrid && $scope.columnsGrid.api) { $scope.columnsGrid.api.setColumnDefs($scope.columnsDefinition); @@ -88,16 +116,16 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q onGridReady : resizeColumns, onCellEditingStopped: refreshRow, singleClickEdit: true, - stopEditingWhenGridLosesFocus: true, columnDefs: $scope.columnsDefinition, rowData: $scope.newModel.content.columnSelectedOfDataset } function rowDragEnter(event){ - $scope.startingDragRow = event.overIndex; + if(!$scope.startingDragRow) $scope.startingDragRow = event.overIndex; } function onRowDragEnd(event){ moveInArray($scope.newModel.content.columnSelectedOfDataset, $scope.startingDragRow, event.overIndex); + delete $scope.startingDragRow; } function resizeColumns(){ @@ -114,6 +142,7 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q return typeof(params.data.name) !== 'undefined'; } function isAggregationEditable(params) { + if (params.data.isCalculated) return false; return params.data.fieldType == "MEASURE" ? true : false; } @@ -123,17 +152,34 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q } function groupRenderer(params) { - return ' '+ (typeof params.value != 'undefined' ? params.value : '') +''; + var value = ''; + if(typeof params.value != 'undefined') value = params.value; + if(typeof params.valueFormatted != 'undefined') value = params.valueFormatted; + return ' '+ value +''; + } + + function groupSelectFormatter(params) { + return $scope.availableGroups[params.value]; + } + + function groupSelectParser(params) { + for (var key in $scope.availableGroups) { + if ($scope.availableGroups.hasOwnProperty(key)) { + if (params.newValue === $scope.availableGroups[key]) { + return key; + } + } + } } function buttonRenderer(params){ var calculator = ''; if(params.data.isCalculated){ - calculator = ''; + calculator = ''; } return calculator + - ''+ + ''+ ' {{::translate.load("sbi.cockpit.widgets.table.columnstyle.icon")}}'+ ' '+ ''+ @@ -234,10 +280,8 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q else $scope.newModel.content.columnSelectedOfDataset[rowIndex].style = {'hiddenColumn': true}; } - $scope.draw = function(rowName) { - for(var k in $scope.newModel.content.columnSelectedOfDataset){ - if($scope.newModel.content.columnSelectedOfDataset[k].alias == rowName) $scope.selectedColumn = $scope.newModel.content.columnSelectedOfDataset[k]; - } + $scope.draw = function(rowIndex) { + $scope.selectedColumn = $scope.newModel.content.columnSelectedOfDataset[rowIndex]; $mdDialog.show({ templateUrl: baseScriptPath+ '/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html', @@ -247,7 +291,7 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q preserveScope: false, autoWrap:false, fullscreen: true, - locals:{model:$scope.newModel, selectedColumn : $scope.selectedColumn}, + locals:{model:$scope.newModel, selectedColumn : $scope.selectedColumn, dialogOptions: {}}, controller: cockpitStyleColumnFunction }).then(function(answer) { console.log("Selected column:", $scope.selectedColumn); @@ -276,10 +320,11 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q scope.translate=sbiModule_translate; scope.cockpitModule_generalOptions = cockpitModule_generalOptions; scope.model = angular.copy(model); - + scope.addGroup = function(){ - if(scope.model.groups) scope.model.groups.push({}); - else scope.model.groups = [{}]; + var id = uuidv4(); + if(scope.model.groups) scope.model.groups.push({id:id}); + else scope.model.groups = [{id:id}]; } scope.deleteGroup = function(i){ @@ -292,6 +337,9 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q } scope.saveGroups = function(){ + for(var k in scope.model.groups){ + if(!scope.model.groups[k].id) scope.model.groups[k].id = uuidv4(); + } $mdDialog.hide(scope.model); } @@ -448,14 +496,27 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q $scope.removeSummaryRow = function(i){ $scope.newModel.settings.summary.list.splice(i,1); } + + $scope.checkForPinnedColumns = function(columns){ + for(var k in columns){ + if(columns[k].pinned) return false; + } + return true; + } $scope.$watch('newModel.settings.summary.enabled',function(newValue,oldValue){ if(newValue){ + if($scope.newModel.settings.summary.style && $scope.newModel.settings.summary.style.pinnedOnly){ + $scope.showNoPinnedColumnWarning = $scope.checkForPinnedColumns($scope.newModel.content.columnSelectedOfDataset); + } if(!$scope.newModel.settings.summary.list) $scope.newModel.settings.summary.list = [{}]; } }) $scope.$watch('newModel.content.columnSelectedOfDataset',function(newValue,oldValue){ + if($scope.newModel.settings.summary && $scope.newModel.settings.summary.style && $scope.newModel.settings.summary.style.pinnedOnly){ + $scope.showNoPinnedColumnWarning = $scope.checkForPinnedColumns(newValue); + } if($scope.columnsGrid.api && newValue){ $scope.columnsGrid.api.setRowData(newValue); $scope.columnsGrid.api.sizeColumnsToFit(); @@ -505,7 +566,7 @@ function advancedTableWidgetEditControllerFunction($scope,$compile,finishEdit,$q var columns = $scope.newModel.content.columnSelectedOfDataset; for(var i = 0; i < columns.length - 1; i++){ for(var j = i + 1; j < columns.length; j++){ - if(columns[i].aliasToShow == columns[j].aliasToShow){ + if(columns[i].aliasToShow.toLowerCase() == columns[j].aliasToShow.toLowerCase()){ return false; } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetEditPropertyTemplate.html index 4888deef34d..52d458e32d3 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetEditPropertyTemplate.html @@ -40,7 +40,7 @@

{{::translate.format(translate.load('sbi.cockpit.widget.configuration'),tran Manage column groups {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.addcolumn')}} - +

@@ -86,13 +86,20 @@

{{::translate.format(translate.load('sbi.cockpit.widget.configuration'),tran

+
+
{{::translate.load('sbi.cockpit.widget.table.summary.noPinnedColumnsWarning')}}
+
- + + + + + - + {{func}} @@ -201,15 +208,15 @@

{{::translate.load('sbi.cockpit.widget.table.rows')}}

-
+
- +
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetTemplate.html index d52f619c16f..9a943c214b8 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/advancedTableWidget/templates/advancedTableWidgetTemplate.html @@ -13,18 +13,18 @@ {{((ngModel.settings.page-1)*ngModel.settings.pagination.itemsNumber+1)}} {{::translate.load('sbi.cockpit.widgets.table.pagination.to')}} {{maxPageNumber()}} {{::translate.load('sbi.cockpit.widgets.table.pagination.of')}} {{totalRows}} -
- +
+
-
- +
+
- {{::translate.load('sbi.cockpit.widgets.table.pagination.page')}} {{ngModel.settings.page}} {{::translate.load('sbi.cockpit.widgets.table.pagination.of')}} {{totalPages}} -
- + {{::translate.load('sbi.cockpit.widgets.table.pagination.page')}} {{ngModel.settings.page}} {{::translate.load('sbi.cockpit.widgets.table.pagination.of')}} {{totalPages}} +
+
-
- +
+
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/chartWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/chartWidget.js index 8581ac43967..09a4dbf1812 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/chartWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/chartWidget.js @@ -121,7 +121,8 @@ function cockpitChartWidgetControllerFunction( $scope.isIE = window.document.documentMode; $scope.model = $scope.ngModel; $scope.local = {}; - if($scope.model.dataset != undefined && $scope.model.dataset.dsId !=-1 && !$scope.model.content.columnSelectedOfDatasetAggregations ){ + + if($scope.model.dataset != undefined && $scope.model.dataset.dsId !=-1 && !$scope.model.content.columnSelectedOfDatasetAggregations ){ angular.copy(cockpitModule_datasetServices.getDatasetById($scope.model.dataset.dsId), $scope.local); $scope.model.content.columnSelectedOfDatasetAggregations = []; for(var i=0;i<$scope.local.metadata.fieldsMeta.length;i++){ @@ -131,6 +132,7 @@ function cockpitChartWidgetControllerFunction( $scope.safeApply(); } if($scope.model.content.columnSelectedOfDatasetAggregations) { + $scope.model.content.columnSelectedOfDatasetAggregations = cockpitModule_widgetServices.checkForUpdatedDataset($scope.model.content.columnSelectedOfDatasetAggregations,$scope.model.dataset.dsId); for(var c in $scope.model.content.columnSelectedOfDatasetAggregations){ if(!$scope.model.content.columnSelectedOfDatasetAggregations[c].aliasToShow) $scope.model.content.columnSelectedOfDatasetAggregations[c].aliasToShow = $scope.model.content.columnSelectedOfDatasetAggregations[c].alias; if($scope.model.content.columnSelectedOfDatasetAggregations[c].fieldType == 'MEASURE' && !$scope.model.content.columnSelectedOfDatasetAggregations[c].aggregationSelected) $scope.model.content.columnSelectedOfDatasetAggregations[c].aggregationSelected = 'SUM'; @@ -536,6 +538,25 @@ function cockpitChartWidgetControllerFunction( $scope.localDataset = {}; $scope.availableAggregations = ["NONE","SUM","AVG","MAX","MIN","COUNT","COUNT_DISTINCT"]; $scope.typesMap = cockpitModule_generalOptions.typesMap; + + $scope.getDatasetAdditionalInfo = function(dsId){ + for(var k in cockpitModule_template.configuration.datasets){ + if(cockpitModule_template.configuration.datasets[k].dsId == dsId) { + $scope.tempDataset = cockpitModule_template.configuration.datasets[k]; + break; + } + } + sbiModule_restServices.restToRootProject(); + sbiModule_restServices.promiseGet('2.0/datasets', 'availableFunctions/' + dsId, "useCache=" + $scope.tempDataset.useCache).then(function(response){ + $scope.datasetAdditionalInfos = response.data; + }, function(response) { + if(response.data && response.data.errors && response.data.errors[0]) $scope.showAction(response.data.errors[0].message); + else $scope.showAction($scope.translate.load('sbi.generic.error')); + }); + } + + if($scope.localModel.dataset && $scope.localModel.dataset.dsId) $scope.getDatasetAdditionalInfo($scope.localModel.dataset.dsId); + $scope.handleEvent=function(event, arg1){ if(event=='init'){ if($scope.localModel.datasetId != undefined){ @@ -551,6 +572,7 @@ function cockpitChartWidgetControllerFunction( }else if(event=='openFilters'){ $scope.somethingChanged = true; }else if(event=='save'){ + $scope.somethingChanged = true; if(checkChartSettings()==undefined){ return } @@ -592,7 +614,7 @@ function cockpitChartWidgetControllerFunction( if($scope.localModel.datasetId){ $scope.localModel.datasetId=null } - + $scope.getDatasetAdditionalInfo(dsId); var ds = cockpitModule_datasetServices.getDatasetById(dsId); if(ds){ if(ds.id.dsId != $scope.localModel.datasetId && ds.id.dsLabel != $scope.localModel.datasetLabel){ @@ -917,16 +939,15 @@ function cockpitChartWidgetControllerFunction( enableFilter: false, enableSorting: false, onGridReady : resizeColumns, - onCellEditingStopped: refreshRow, singleClickEdit: true, - stopEditingWhenGridLosesFocus: true, + onCellEditingStopped: refreshRow, columnDefs: $scope.columnsDefition, rowData: $scope.localModel.columnSelectedOfDatasetAggregations } function buttonRenderer(params){ if(params.data.isCalculated){ - return '' + + return '' + '{{::translate.load("sbi.cockpit.widgets.table.column.delete")}}'; } @@ -988,6 +1009,7 @@ function cockpitChartWidgetControllerFunction( $scope.reloadWidgetsByChartEvent = function(item){ + if($scope.ngModel.cliccable == false) return var event= item.select != undefined ? item.select : item; var crossParameters= createCrossParameters(item); var chartType = $scope.ngModel.content.chartTemplate.CHART.type; @@ -1301,7 +1323,7 @@ function setAggregationsOnChartEngine(wconf,sbiModule_util){ var chartSeries = chartTemplate.CHART.VALUES.SERIE; for(var i = 0; i < chartSeries.length; i++){ - var index = sbiModule_util.findInArray(wconf.columnSelectedOfDatasetAggregations, 'alias', chartSeries[i].name); + var index = sbiModule_util.findInArray(wconf.columnSelectedOfDatasetAggregations, 'alias', chartSeries[i].column); var obj = {}; obj['name'] = chartSeries[i].column; obj['aggregationSelected'] = wconf.columnSelectedOfDatasetAggregations[index].aggregationSelected; @@ -1313,6 +1335,7 @@ function setAggregationsOnChartEngine(wconf,sbiModule_util){ if(wconf.columnSelectedOfDatasetAggregations[index].isCalculated) { obj['isCalculated'] = wconf.columnSelectedOfDatasetAggregations[index].isCalculated; obj['formula'] = wconf.columnSelectedOfDatasetAggregations[index].formula; + obj['datasetOrTableFlag'] = wconf.columnSelectedOfDatasetAggregations[index].datasetOrTableFlag; } aggregations.push(obj); } @@ -1322,9 +1345,7 @@ function setAggregationsOnChartEngine(wconf,sbiModule_util){ if(chartTemplate.CHART.VALUES.CATEGORY){ var chartCategory= chartTemplate.CHART.VALUES.CATEGORY; - if(chartCategory.name=="" || chartCategory.name==null || chartCategory.name==undefined){ - chartCategory.name=chartCategory.column - } + if(Array.isArray(chartCategory)){ for(var i = 0; i < chartCategory.length; i++){ @@ -1338,12 +1359,15 @@ function setAggregationsOnChartEngine(wconf,sbiModule_util){ aggregations.push(obj); } } else { + if(chartCategory.name=="" || chartCategory.name==null || chartCategory.name==undefined){ + chartCategory.name=chartCategory.column + } var obj = {}; obj['name'] = chartCategory.column; obj['alias'] = chartCategory.name; obj['aliasToShow'] = chartCategory.alias; - obj['orderType'] = chartCategory.orderType; - obj['orderColumn'] = chartCategory.orderColumn; + obj['orderType'] = chartCategory.drillOrder && chartCategory.drillOrder[chartCategory.column] ? chartCategory.drillOrder[chartCategory.column].orderType : chartCategory.orderType ; + obj['orderColumn'] = chartCategory.drillOrder && chartCategory.drillOrder[chartCategory.column] ? chartCategory.drillOrder[chartCategory.column].orderColumn : chartCategory.orderColumn ; obj['fieldType'] = "ATTRIBUTE"; aggregations.push(obj); @@ -1367,8 +1391,8 @@ function setAggregationsOnChartEngine(wconf,sbiModule_util){ groupby['orderType'] = chartCategory.drillOrder[subs] ? chartCategory.drillOrder[subs].orderType : obj.orderType ; groupby['orderColumn'] = chartCategory.drillOrder[subs] ? chartCategory.drillOrder[subs].orderColumn : obj.orderColumn; } else { - groupby['orderType'] = chartCategory.orderType; - groupby['orderColumn'] = chartCategory.orderColumn; + groupby['orderType'] = chartCategory.orderType ? chartCategory.orderType : ""; + groupby['orderColumn'] = chartCategory.orderColumn ? chartCategory.orderColumn : ""; } aggregations.push(groupby); } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/templates/chartWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/templates/chartWidgetEditPropertyTemplate.html index 269ce905bd6..36c0470f5d8 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/templates/chartWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/chartWidget/templates/chartWidgetEditPropertyTemplate.html @@ -22,7 +22,7 @@

{{translate.format(translate.load('sbi.cockpit.widget.configuration'),transl
{{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.tablecolumns')}} - +
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidget.js new file mode 100644 index 00000000000..3cd85000cf9 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidget.js @@ -0,0 +1,132 @@ +/* +ùKnowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +(function() { + angular.module('cockpitModule') + .directive('cockpitCustomchartWidget',function(){ + return{ + templateUrl: baseScriptPath+ '/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetTemplate.html', + controller: cockpitCustomChartControllerFunction, + compile: function (tElement, tAttrs, transclude) { + return { + pre: function preLink(scope, element, attrs, ctrl, transclud) { + }, + post: function postLink(scope, element, attrs, ctrl, transclud) { + element.ready(function () { + scope.initWidget(); + }); + } + }; + } + } + }) + +function cockpitCustomChartControllerFunction( + $scope, + $mdDialog, + $mdToast, + $timeout, + $mdPanel, + $q, + $sce, + $filter, + cockpitModule_generalServices, + sbiModule_translate, + datastore + ){ + $scope.datastore = datastore; + $scope.translate = sbiModule_translate; + $scope.getTemplateUrl = function(template){ + return cockpitModule_generalServices.getTemplateUrl('customChartWidget',template); + } + + if(!$scope.ngModel.style) $scope.ngModel.style = {}; + + if(!$scope.ngModel.js) { + $scope.ngModel.css = {}; + $scope.ngModel.html = {}; + $scope.ngModel.js = {}; + } + + $scope.init=function(element,width,height){ + $scope.showWidgetSpinner(); + $scope.refreshWidget(null, 'init'); + } + datastore = angular.copy(datastore) + datastore.clickManager = function(column,value){ + $scope.doSelection(column,value); + } + + $scope.refresh = function(element,width,height, datasetRecords,nature){ + $scope.jsError = false; + $scope.showWidgetSpinner(); + var thisElement = angular.element( document.querySelector( '#w'+$scope.ngModel.id+' .htmlRenderer' ) )[0]; + thisElement.innerHTML = ''; + thisElement.innerHTML = $sce.trustAsHtml($scope.ngModel.html.code); + if(datasetRecords){ + try { + datastore.setData(datasetRecords); + + if($scope.ngModel.js) { + var tempJS = $sce.trustAs($sce.JS, $scope.ngModel.js.code).$$unwrapTrustedValue(); + if(!tempJS.match(/(\$scope|\$destroy|datastore\.setData)/g)) eval(tempJS); + else { + $scope.jsError = $scope.translate.load('kn.cockpit.custom.code.unsafe'); + } + } + $scope.hideWidgetSpinner(); + } catch(e){ + $scope.hideWidgetSpinner(); + $scope.jsError = e; + } + } + } + + $scope.reinit = function(){ + $scope.showWidgetSpinner(); + $scope.refreshWidget(); + } + + $scope.editWidget=function(index){ + var finishEdit=$q.defer(); + var config = { + attachTo: angular.element(document.body), + controller: customChartWidgetEditControllerFunction, + disableParentScroll: true, + templateUrl: $scope.getTemplateUrl('customChartWidgetEditPropertyTemplate'), + position: $mdPanel.newPanelPosition().absolute().center(), + fullscreen :true, + hasBackdrop: true, + clickOutsideToClose: false, + escapeToClose: false, + focusOnOpen: true, + preserveScope: false, + locals: {finishEdit:finishEdit,model:$scope.ngModel}, + }; + $mdPanel.open(config); + return finishEdit.promise; + } + + +} + + /** + * register the widget in the cockpitModule_widgetConfigurator factory + */ + addWidgetFunctionality("customchart",{'initialDimension':{'width':5, 'height':5},'updateble':true,'cliccable':true}); + +})(); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidgetEdit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidgetEdit.js new file mode 100644 index 00000000000..e6cc5058b1f --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/customChartWidgetEdit.js @@ -0,0 +1,306 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ +angular + .module('cockpitModule') + .controller('customChartWidgetEditControllerFunction',customChartWidgetEditControllerFunction) + +function customChartWidgetEditControllerFunction( + $scope, + finishEdit, + model, + $filter, + $mdDialog, + mdPanelRef, + sbiModule_translate, + cockpitModule_template, + cockpitModule_datasetServices, + cockpitModule_generalOptions, + datastore){ + + $scope.translate = sbiModule_translate; + $scope.newModel = angular.copy(model); + $scope.typesMap = cockpitModule_generalOptions.typesMap; + $scope.availableAggregations = ["NONE","SUM","AVG","MAX","MIN","COUNT","COUNT_DISTINCT"]; + + if($scope.newModel.css.opened) $scope.newModel.css.opened = false; + if($scope.newModel.html.opened) $scope.newModel.html.opened = false; + if(!$scope.newModel.js.opened) $scope.newModel.js.opened = true; + + $scope.toggleLanguage = function(language){ + var languages = ['css','html','js']; + for(var k in languages){ + if(languages[k] != language) $scope.newModel[languages[k]].opened = false; + else $scope.newModel[language].opened = !$scope.newModel[language].opened; + } + } + + $scope.changeDS = function(id){ + $scope.newModel.content.columnSelectedOfDataset = cockpitModule_datasetServices.getDatasetById(id).metadata.fieldsMeta; + for(var c in $scope.newModel.content.columnSelectedOfDataset){ + if(!$scope.newModel.content.columnSelectedOfDataset[c].aliasToShow) $scope.newModel.content.columnSelectedOfDataset[c].aliasToShow = $scope.newModel.content.columnSelectedOfDataset[c].alias; + if($scope.newModel.content.columnSelectedOfDataset[c].fieldType == 'MEASURE' && !$scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected) $scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected = 'SUM'; + if($scope.newModel.content.columnSelectedOfDataset[c].fieldType == 'MEASURE' && !$scope.newModel.content.columnSelectedOfDataset[c].funcSummary) $scope.newModel.content.columnSelectedOfDataset[c].funcSummary = $scope.newModel.content.columnSelectedOfDataset[c].aggregationSelected; + } + $scope.getDatasetAdditionalInfo(id); + $scope.columnsGrid.api.setRowData($scope.newModel.content.columnSelectedOfDataset); + } + + $scope.getDatasetAdditionalInfo = function(dsId){ + for(var k in cockpitModule_template.configuration.datasets){ + if(cockpitModule_template.configuration.datasets[k].dsId == dsId) { + $scope.localDataset = cockpitModule_template.configuration.datasets[k]; + break; + } + } + } + if($scope.newModel.dataset && $scope.newModel.dataset.dsId) $scope.getDatasetAdditionalInfo($scope.newModel.dataset.dsId); + + function getColumnsDefinition() { + $scope.availableGroups = ['']; + + $scope.columnsDefinition = [ + {headerName: 'Name', field:'alias'}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.alias'), field:'aliasToShow',"editable":true,cellRenderer:editableCell, cellClass: 'editableCell'}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.type'), field: 'fieldType'}, + {headerName: 'Data Type', field: 'type',cellRenderer:typeCell}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.aggregation'), field: 'aggregationSelected', cellRenderer: aggregationRenderer,"editable":isAggregationEditable, cellClass: 'editableCell', + cellEditor:"agSelectCellEditor",cellEditorParams: {values: $scope.availableAggregations}}, + {headerName:"",cellRenderer: buttonRenderer,"field":"valueId","cellStyle":{"border":"none !important","text-align": "right","display":"inline-flex","justify-content":"flex-end"},width: 100,suppressSizeToFit:true, tooltip: false, + headerClass:'header-cell-buttons'}]; + + if($scope.columnsGrid && $scope.columnsGrid.api) { + $scope.columnsGrid.api.setColumnDefs($scope.columnsDefinition); + $scope.columnsGrid.api.setRowData($scope.newModel.content.columnSelectedOfDataset); + resizeColumns(); + } + } + getColumnsDefinition(); + + $scope.columnsGrid = { + angularCompileRows: true, + domLayout:'autoHeight', + enableColResize: false, + enableFilter: false, + enableSorting: false, + onGridReady : resizeColumns, + onViewportChanged: resizeColumns, + onCellEditingStopped: refreshRow, + singleClickEdit: true, + columnDefs: $scope.columnsDefinition, + rowData: $scope.newModel.content.columnSelectedOfDataset + } + + function resizeColumns(){ + $scope.columnsGrid.api.sizeColumnsToFit(); + } + + function editableCell(params){ + return typeof(params.value) !== 'undefined' ? ' '+params.value+''+params.value+'' : ''; + } + function typeCell(params){ + return " "+$scope.typesMap[params.value].label; + } + function isInputEditable(params) { + return typeof(params.data.name) !== 'undefined'; + } + function isAggregationEditable(params) { + if (params.data.isCalculated) return false; + return params.data.fieldType == "MEASURE" ? true : false; + } + + function aggregationRenderer(params) { + var aggregation = ' '+params.value+''; + return params.data.fieldType == "MEASURE" && !params.data.isCalculated ? aggregation : ''; + } + + function groupRenderer(params) { + return ' '+ (typeof params.value != 'undefined' ? params.value : '') +''; + } + + function buttonRenderer(params){ + var calculator = ''; + if(params.data.isCalculated){ + calculator = ''; + } + + return calculator + + '{{::translate.load("sbi.cockpit.widgets.table.column.delete")}}'; + } + + function refreshRow(cell){ + if(cell.data.fieldType == 'MEASURE' && !cell.data.aggregationSelected) cell.data.aggregationSelected = 'SUM'; + if(cell.data.fieldType == 'MEASURE' && cell.data.aggregationSelected) cell.data.funcSummary = cell.data.aggregationSelected == 'NONE' ? 'SUM' : cell.data.aggregationSelected; + if(cell.data.isCalculated) cell.data.alias = cell.data.aliasToShow; + $scope.columnsGrid.api.redrawRows({rowNodes: [$scope.columnsGrid.api.getDisplayedRowAtIndex(cell.rowIndex)]}); + } + + $scope.deleteColumn = function(rowName,event) { + for(var k in $scope.newModel.content.columnSelectedOfDataset){ + if($scope.newModel.content.columnSelectedOfDataset[k].alias == rowName) var item = $scope.newModel.content.columnSelectedOfDataset[k]; + } + var index=$scope.newModel.content.columnSelectedOfDataset.indexOf(item); + $scope.newModel.content.columnSelectedOfDataset.splice(index,1); + if($scope.newModel.settings.sortingColumn == item.aliasToShow){ + $scope.newModel.settings.sortingColumn = null; + } + } + + $scope.openListColumn = function(){ + if($scope.newModel.dataset == undefined || $scope.newModel.dataset.dsId == undefined){ + $scope.showAction($scope.translate.load("sbi.cockpit.table.missingdataset")); + }else{ + $mdDialog.show({ + templateUrl: baseScriptPath+ '/directives/cockpit-columns-configurator/templates/cockpitColumnsOfDataset.html', + parent : angular.element(document.body), + clickOutsideToClose:true, + escapeToClose :true, + preserveScope: true, + autoWrap:false, + locals: {model:$scope.newModel}, + fullscreen: true, + controller: controllerCockpitColumnsConfigurator + }).then(function(answer) { + }, function() { + }); + } + } + + function controllerCockpitColumnsConfigurator($scope,sbiModule_translate,$mdDialog,model,cockpitModule_datasetServices,cockpitModule_generalOptions,$filter){ + $scope.translate=sbiModule_translate; + + $scope.cockpitModule_generalOptions=cockpitModule_generalOptions; + $scope.model = model; + $scope.localDataset = {}; + + if($scope.model.dataset && $scope.model.dataset.dsId){ + angular.copy(cockpitModule_datasetServices.getDatasetById($scope.model.dataset.dsId), $scope.localDataset); + } else{ + $scope.model.dataset= {}; + angular.copy([], $scope.model.dataset.metadata.fieldsMeta); + } + + $scope.filterColumns = function(){ + var tempColumnsList = $filter('filter')($scope.localDataset.metadata.fieldsMeta,$scope.columnsSearchText); + $scope.columnsGridOptions.api.setRowData(tempColumnsList); + } + + $scope.columnsGridOptions = { + enableColResize: false, + enableFilter: true, + enableSorting: true, + pagination: true, + paginationAutoPageSize: true, + onGridSizeChanged: resizeColumns, + onViewportChanged: resizeColumns, + rowSelection: 'multiple', + rowMultiSelectWithClick: true, + defaultColDef: { + suppressMovable: true, + tooltip: function (params) { + return params.value; + }, + }, + columnDefs :[{"headerName":"Column","field":"alias",headerCheckboxSelection: true, checkboxSelection: true}, + {"headerName":"Field Type","field":"fieldType"}, + {"headerName":"Type","field":"type"}], + rowData : $scope.localDataset.metadata.fieldsMeta + }; + + function resizeColumns(){ + $scope.columnsGridOptions.api.sizeColumnsToFit(); + } + + $scope.saveColumnConfiguration=function(){ + model = $scope.model; + + if(model.content.columnSelectedOfDataset == undefined){ + model.content.columnSelectedOfDataset = []; + } + for(var i in $scope.columnsGridOptions.api.getSelectedRows()){ + var obj = $scope.columnsGridOptions.api.getSelectedRows()[i]; + obj.aggregationSelected = 'SUM'; + obj.funcSummary = 'SUM'; + obj.typeSelected = obj.type; + obj.label = obj.alias; + obj.aliasToShow = obj.alias; + model.content.columnSelectedOfDataset.push(obj); + } + + $mdDialog.hide(); + } + + $scope.cancelConfiguration=function(){ + $mdDialog.cancel(); + } + } + + $scope.$watch('newModel.content.columnSelectedOfDataset',function(newValue,oldValue){ + if($scope.columnsGrid.api && newValue){ + $scope.columnsGrid.api.setRowData(newValue); + $scope.columnsGrid.api.sizeColumnsToFit(); + } + },true) + + //Codemirror initializer + $scope.codemirrorLoaded = function(_editor) { + $scope._doc = _editor.getDoc(); + $scope._editor = _editor; + _editor.focus(); + $scope._doc.markClean() + _editor.on("beforeChange", function() {}); + _editor.on("change", function() {}); + }; + + //codemirror options + $scope.editorOptionsCss = { + theme: 'eclipse', + lineWrapping: true, + lineNumbers: true, + mode: {name:'css'}, + onLoad: $scope.codemirrorLoaded + }; + $scope.editorOptionsHtml = { + theme: 'eclipse', + lineWrapping: true, + lineNumbers: true, + mode: {name: "xml", htmlMode: true}, + onLoad: $scope.codemirrorLoaded + }; + $scope.editorOptionsJs = { + theme: 'eclipse', + lineWrapping: true, + lineNumbers: true, + mode: {name: "javascript"}, + onLoad: $scope.codemirrorLoaded + }; + + $scope.saveConfiguration=function(){ + mdPanelRef.close(); + angular.copy($scope.newModel,model); + $scope.$destroy(); + finishEdit.resolve(); + } + $scope.cancelConfiguration=function(){ + mdPanelRef.close(); + $scope.$destroy(); + finishEdit.reject(); + } + + + +} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetEditPropertyTemplate.html new file mode 100644 index 00000000000..5cfd37315c2 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetEditPropertyTemplate.html @@ -0,0 +1,115 @@ + + + +
+

{{::translate.load('kn.cockpit.custom.editwidget')}}

+ +
+
+ + + + + + + + + + + + + +
+ + {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.addcolumn')}} + +
+
+ + +
+
+
+
+ + +
+ +
+ + +
+ +

{{::translate.load('kn.cockpit.html.css')}}

+ + + + +
+
+ + + +
+ + + +
+ +

{{::translate.load('kn.cockpit.html.html')}}

+ + + + +
+
+ + + +
+ + + +
+ +

Javascript

+ + + + +
+
+ + + +
+
+ +
+
+
+ + + + + + + + + + + + + +
+
+
+ + + {{::translate.load('sbi.generic.cancel')}} + + + {{::translate.load('sbi.generic.save')}} + + +
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetTemplate.html new file mode 100644 index 00000000000..e2db0612298 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/customChartWidget/templates/customChartWidgetTemplate.html @@ -0,0 +1,5 @@ + +
+
+
+
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/discoveryWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/discoveryWidget.js index 08a9381ec2d..b2f1cdb07d5 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/discoveryWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/discoveryWidget.js @@ -74,8 +74,10 @@ along with this program. If not, see . "enabled" : true }, "facets" : { - "selection" : true - } + "selection" : true, + "enabled" : true + }, + "textEnabled" : true }; }else $scope.ngModel.settings.page = 1; @@ -91,6 +93,7 @@ along with this program. If not, see . $scope.ngModel.search = {}; } + function setDefaultTextSearch() { if($scope.ngModel.settings && $scope.ngModel.settings.defaultTextSearch){ if($scope.ngModel.settings.defaultTextSearchType == 'static') $scope.ngModel.search.text = $scope.ngModel.settings.defaultTextSearchValue; if($scope.ngModel.settings.defaultTextSearchType == 'driver') $scope.ngModel.search.text = cockpitModule_analyticalDrivers[$scope.ngModel.settings.defaultTextSearchValue]; @@ -103,6 +106,10 @@ along with this program. If not, see . } } } + } + + setDefaultTextSearch(); + $scope.facets = []; $scope.gridOptions = { @@ -114,8 +121,7 @@ along with this program. If not, see . onSortChanged: changeSorting, onCellClicked: handleClick, onColumnResized: columnResized, - getRowHeight: getRowHeight, - stopEditingWhenGridLosesFocus:true + getRowHeight: getRowHeight }; function getRowHeight(params){ @@ -206,6 +212,7 @@ along with this program. If not, see . } $scope.reinit = function(){ + setDefaultTextSearch(); $scope.refreshWidget(null, 'init'); } @@ -238,7 +245,6 @@ along with this program. If not, see . if($scope.ngModel.settings.table && $scope.ngModel.settings.table.enabled){ $scope.gridOptions.headerHeight = !$scope.ngModel.style.th.enabled && 0; if(nature == 'init'){ - if(typeof $scope.ngModel.settings.textEnabled == 'undefined') $scope.ngModel.settings.textEnabled = true; $scope.columns = $scope.getColumns(datasetRecords.metaData.fields); $scope.updateDates(); $scope.gridOptions.api.setColumnDefs($scope.columns); @@ -434,14 +440,14 @@ along with this program. If not, see . if($scope.dimensions && $scope.dimensions.width<600){ $scope.toggleMenu(); } - if($scope.ngModel.settings.facets.selection){ + if($scope.ngModel.settings.facets.selection == true){ $scope.ngModel.search.facets = {}; if($scope.template.configuration && (cockpitModule_template.configuration.filters[$scope.ngModel.dataset.label] && cockpitModule_template.configuration.filters[$scope.ngModel.dataset.label][group]==item.column_1) || ($scope.template.configuration.aggregations && $scope.template.configuration.aggregations.length > 0 && $scope.template.configuration.aggregations[0].selection && $scope.template.configuration.aggregations[0].selection[$scope.ngModel.dataset.label+'.'+group] == item.column_1)){ $scope.deleteFilterSelection(group, item.column_1); }else{ - $scope.doSelection(group, item.column_1, null, null, item, null, undefined, !$scope.ngModel.settings.facets.selection); + $scope.doSelection(group, item.column_1, null, null, item, null, undefined, !$scope.ngModel.settings.facets.selection,'selection'); } }else{ if(!$scope.ngModel.search.facets) $scope.ngModel.search.facets = {}; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/templates/discoveryWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/templates/discoveryWidgetEditPropertyTemplate.html index 57e4d056b1e..aabaf66b6b4 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/templates/discoveryWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/discoveryWidget/templates/discoveryWidgetEditPropertyTemplate.html @@ -54,7 +54,8 @@

{{::translate.load('kn.cockpit.discovery.edit')}}

- {{::translate.load('kn.cockpit.discovery.facets.enable')}} + {{::translate.load('kn.cockpit.discovery.facets.enable.tooltip')}} + {{::translate.load('kn.cockpit.discovery.facets.enable')}}
Closed by default @@ -86,17 +87,17 @@

{{::translate.load('kn.cockpit.discovery.edit')}}

- + {{type.label}} - + - + {{key}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidget.js index 959851950fa..4cd13da5184 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidget.js @@ -76,7 +76,7 @@ along with this program. If not, see . cockpitModule_template){ $scope.getTemplateUrl = function(template){ - return cockpitModule_generalServices.getTemplateUrl('htmlWidget',template); + return $sce.trustAsResourceUrl(cockpitModule_generalServices.getTemplateUrl('htmlWidget',template)); } @@ -86,7 +86,7 @@ along with this program. If not, see . $scope.columnRegex = /(?:\[kn-column=\'([a-zA-Z0-9\_\-\s]+)\'(?:\s+row=\'(\d*)\')?(?:\s+aggregation=\'(AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)\')?(?:\s+precision=\'(\d)\')?(\s+format)?\s?\])/g; $scope.rowsRegex = /(?:\[kn-column=\'([a-zA-Z0-9\_\-\s]+)\'(?:\s+row=\'(\d+)\'){1}(?:\s+aggregation=\'(AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)\')?(?:\s+precision=\'(\d)\')?(\s+format)?\s?\])/g; $scope.noAggregationsExistRegex = /\[kn-column=\'[a-zA-Z0-9\_\-\s]+\'(?:\s+row=\'\d+\')?(?!\s+aggregation=\'(AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)\')(?:\s+precision=\'(?:\d)\')?(?:\s+format)?\s?\]/g; - $scope.limitRegex = /<[\s\w\=\"\'\-\[\]]*(?<=limit=)"([\d]+)"[\s\w\=\"\'\-\[\]]*>/g; + $scope.limitRegex = /<[\s\w\=\"\'\-\[\]]*(?!limit=)"([\-\d]+)"[\s\w\=\"\'\-\[\]]*>/g; $scope.aggregationsRegex = /(?:\[kn-column=[\']{1}([a-zA-Z0-9\_\-\s]+)[\']{1}(?:\s+aggregation=[\']{1}(AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)[\']{1}){1}(?:\s+precision=\'(\d)\')?(\s+format)?\])/g; $scope.aggregationRegex = /(?:\[kn-column=[\']{1}([a-zA-Z0-9\_\-\s]+)[\']{1}(?:\s+aggregation=[\']{1}(AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)[\']{1}){1}(?:\s+precision=\'(\d)\')?(\s+format)?\])/; $scope.paramsRegex = /(?:\[kn-parameter=[\'\"]{1}([a-zA-Z0-9\_\-\s]+)[\'\"]{1}\])/g; @@ -179,7 +179,8 @@ along with this program. If not, see . var str = $scope.ngModel.cssToRender + $scope.ngModel.htmlToRender; var tempMaxRow = 1; var repeaters = str.replace($scope.limitRegex, function(match, p1){ - if(p1>tempMaxRow) tempMaxRow = parseInt(p1)+1; + if(parseInt(p1) == -1) tempMaxRow = -1; + else if(p1>tempMaxRow) tempMaxRow = parseInt(p1)+1; }) var occurrencies = str.replace($scope.rowsRegex,function(match,p1,p2){ if(p2>=tempMaxRow) tempMaxRow = parseInt(p2)+1; @@ -227,7 +228,7 @@ along with this program. If not, see . //Get the dataset column name from the readable name. ie: 'column_1' for the name 'id' $scope.getColumnFromName = function(name,ds,aggregation){ for(var i in ds.metaData.fields){ - if(typeof ds.metaData.fields[i].header != 'undefined' && ds.metaData.fields[i].header == (aggregation ? name+'_'+aggregation : name)){ + if(typeof ds.metaData.fields[i].header != 'undefined' && ds.metaData.fields[i].header.toLowerCase() == (aggregation ? name+'_'+aggregation : name).toLowerCase()){ return {'name':ds.metaData.fields[i].name,'type':ds.metaData.fields[i].type }; } } @@ -298,6 +299,7 @@ along with this program. If not, see . if(eval($scope.checkAttributePlaceholders(allElements[i].getAttribute('kn-repeat')))){ allElements[i].removeAttribute("kn-repeat"); var limit = allElements[i].hasAttribute("limit") && (allElements[i].hasAttribute("limit") <= $scope.htmlDataset.rows.length) ? allElements[i].getAttribute('limit') : $scope.htmlDataset.rows.length; + if(allElements[i].hasAttribute("limit") && allElements[i].getAttribute('limit') == -1) limit = $scope.htmlDataset.rows.length; if(allElements[i].hasAttribute("limit")) allElements[i].removeAttribute("limit"); var repeatedElement = angular.copy(allElements[i]); var tempElement; @@ -337,8 +339,10 @@ along with this program. If not, see . do { if (allElements[j] && allElements[j].hasAttribute("kn-if")){ var condition = allElements[j].getAttribute("kn-if").replace($scope.columnRegex, $scope.ifConditionReplacer); + condition = condition.replace($scope.activeSelectionsRegex, $scope.activeSelectionsReplacer); condition = condition.replace($scope.paramsRegex, $scope.ifConditionParamsReplacer); condition = condition.replace($scope.calcRegex, $scope.calcReplacer); + condition = condition.replace($scope.variablesRegex, $scope.variablesReplacer); if(eval(condition)){ allElements[j].removeAttribute("kn-if"); }else{ @@ -412,9 +416,13 @@ along with this program. If not, see . //Replacers $scope.activeSelectionsReplacer = function(match,column){ - if(cockpitModule_template.configuration.filters[$scope.datasetLabel] && cockpitModule_template.configuration.filters[$scope.datasetLabel][column]){ - return cockpitModule_template.configuration.filters[$scope.datasetLabel][column]; - }else return null; + if(cockpitModule_template.getSelections() && cockpitModule_template.getSelections().length > 0){ + var selections = cockpitModule_template.getSelections(); + for(var k in selections){ + if(selections[k].ds == $scope.datasetLabel && selections[k].columnName == column) return selections[k].value; + } + } + return null; } $scope.calcReplacer = function(match,p1,min,max,precision,format){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidgetEdit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidgetEdit.js index b66a8857e24..cfceb97fa39 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidgetEdit.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/htmlWidgetEdit.js @@ -19,16 +19,23 @@ angular .module('cockpitModule') .controller('htmlWidgetEditControllerFunction',htmlWidgetEditControllerFunction) -function htmlWidgetEditControllerFunction($scope,finishEdit,model,sbiModule_translate,$mdDialog,mdPanelRef,$mdToast,$timeout,cockpitModule_datasetServices,cockpitModule_analyticalDrivers,cockpitModule_helperDescriptors){ +function htmlWidgetEditControllerFunction($scope,finishEdit,model,sbiModule_translate,$mdDialog,mdPanelRef,$mdToast,$timeout,cockpitModule_datasetServices,cockpitModule_analyticalDrivers,cockpitModule_analyticalDriversUrls,cockpitModule_helperDescriptors,cockpitModule_properties){ $scope.translate=sbiModule_translate; $scope.newModel = angular.copy(model); $scope.helper = {'column' : {},'parameter':{}}; $scope.formattedAnalyticalDrivers = []; $scope.aggregations = [{'name':'SUM'},{'name':'AVG'},{'name':'MIN'},{'name':'MAX'},{'name':'COUNT'},{'name':'COUNT_DISTINCT'}]; - for(var a in cockpitModule_analyticalDrivers){ - $scope.formattedAnalyticalDrivers.push({'name':a}); + function getAnalyticalDrivers(){ + var tempAnalyticalDrivers = []; + for(var k in cockpitModule_analyticalDriversUrls){ + var url = cockpitModule_analyticalDriversUrls[k].url; + tempAnalyticalDrivers.push({name:k, value:url}); + } + return tempAnalyticalDrivers; } + + $scope.formattedAnalyticalDrivers = getAnalyticalDrivers(); if($scope.newModel.cssOpened) $scope.newModel.cssOpened = false; @@ -36,6 +43,11 @@ function htmlWidgetEditControllerFunction($scope,finishEdit,model,sbiModule_tran tag.opened = !tag.opened; } + for(var k in cockpitModule_properties.VARIABLES){ + if($scope.availableVariables) $scope.availableVariables.push({name:k}); + else $scope.availableVariables = [{name:k}]; + } + $scope.$watch('newModel.dataset.dsId',function(newValue,oldValue){ if(newValue){ $scope.availableDatasets=cockpitModule_datasetServices.getAvaiableDatasets(); @@ -50,10 +62,11 @@ function htmlWidgetEditControllerFunction($scope,finishEdit,model,sbiModule_tran }else{ if($scope.newModel.content && $scope.newModel.content.columnSelectedOfDataset) $scope.newModel.content.columnSelectedOfDataset = []; } - $scope.helper.tags = cockpitModule_helperDescriptors.htmlHelperJSON(newValue,$scope.dataset ? $scope.dataset.metadata.fieldsMeta : null,$scope.formattedAnalyticalDrivers,$scope.aggregations,$scope.newModel.cross,$scope.availableDatasets); + $scope.helper.tags = cockpitModule_helperDescriptors.htmlHelperJSON(newValue,$scope.dataset ? $scope.dataset.metadata.fieldsMeta : null,$scope.formattedAnalyticalDrivers,$scope.aggregations,$scope.newModel.cross,$scope.availableDatasets, $scope.availableVariables); }) + $scope.insertCode = function(tag){ var tempString = tag.tag; for(var i in tag.inputs){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/templates/htmlWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/templates/htmlWidgetEditPropertyTemplate.html index bfea4071dac..c8b65814f94 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/templates/htmlWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/htmlWidget/templates/htmlWidgetEditPropertyTemplate.html @@ -63,7 +63,7 @@

{{translate.load('kn.cockpit.html.availabletags')}} - {{opt.name}} + {{opt.name}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidget.js index 73d864ff717..e9ce9751011 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidget.js @@ -96,8 +96,7 @@ along with this program. If not, see . post: function postLink(scope, element, attrs, ctrl, transclud) { element.ready(function () { scope.initWidget(); - scope.createMap(); - scope.showWidgetSpinner(); + scope.initializeTemplate(); }); } }; @@ -168,6 +167,22 @@ along with this program. If not, see . $scope.columnsConfig = {} //layers with just columns definition $scope.optionSidenavId = "optionSidenav-" + Math.random(); // random id for sidenav id $scope.layerVisibility = []; + $scope.exploded = {}; // is heatp/cluster exploded? + $scope.zoomControl = undefined; // Zoom control on map + $scope.scaleControl = undefined; // Scale indicator + $scope.mouseWheelZoomInteraction = undefined; // Manage the mouse wheel on map + + + $scope.init = function(element,width,height) { + + // Prevent errors about $digest + $timeout(function() { + $scope.initializeTemplate(); + $scope.createMap(); + $scope.addAllLayers(); + $scope.setMapSize(); + }); + }; $scope.realTimeSelections = cockpitModule_widgetServices.realtimeSelections; //set a watcher on a variable that can contains the associative selections for realtime dataset @@ -324,25 +339,20 @@ along with this program. If not, see . $scope.reinit = function(){ - var isNew = ($scope.layers.length == 0); - if (isNew) { - $scope.createMap(); - } else { - // Delete all layers - $scope.map.getLayers().clear(); - $scope.clearInternalData(); - } - - $scope.resetFilter(); - $scope.addAllLayers(); + // Prevent errors about $digest + $timeout(function() { + var nature = "refresh"; + $scope.refreshWidget(null, nature); + }); + } + $scope.setMapSize = function() { if (!$scope.map.getSize()){ $scope.map.setSize([cockpitModule_widgetConfigurator.map.initialDimension.width, cockpitModule_widgetConfigurator.map.initialDimension.height]); }else{ $scope.map.setSize($scope.map.getSize()); } - $scope.map.renderSync(); } $mdSidenav($scope.optionSidenavId, true).then( @@ -362,12 +372,28 @@ along with this program. If not, see . $scope.sideNavOpened = optionSidenav.isOpen(); } + $scope.clearAllLayers = function() { + $scope.map.setLayerGroup(new ol.layer.Group()); + } + $scope.refresh = function(element,width,height, data, nature, associativeSelection, changedChartType, chartConf, options) { if (nature == 'fullExpand' || nature == 'resize'){ $timeout(function() { $scope.map.updateSize(); }, 500); return; + } else if (nature == "refresh") { + // Delete all layers + $scope.clearAllLayers(); + $scope.clearInternalData(); + + $scope.resetFilter(); + + $scope.addAllLayers(); + $scope.setZoomControl(); + $scope.setScaleControl(); + $scope.setMouseWheelZoomInteraction(); + $scope.setMapSize(); } if (!options) options = {}; @@ -451,29 +477,49 @@ along with this program. If not, see . } $scope.initializeTemplate = function (){ - return $q(function(resolve, reject) { - if (!$scope.ngModel.content.currentView) $scope.ngModel.content.currentView = {}; - if (!$scope.ngModel.content.layers) $scope.ngModel.content.layers = []; - if (!$scope.ngModel.content.baseLayersConf) $scope.ngModel.content.baseLayersConf = []; - if (!$scope.ngModel.content.columnSelectedOfDataset) $scope.ngModel.content.columnSelectedOfDataset = {} ; - - if (!$scope.ngModel.content.currentView.center) $scope.ngModel.content.currentView.center = [0,0]; - if (!$scope.ngModel.content.mapId){ - $scope.ngModel.content.mapId = 'map-' + $scope.ngModel.id; + if (!$scope.ngModel.content.currentView) $scope.ngModel.content.currentView = {}; + if (!$scope.ngModel.content.layers) $scope.ngModel.content.layers = []; + if (!$scope.ngModel.content.baseLayersConf) $scope.ngModel.content.baseLayersConf = []; + if (!$scope.ngModel.content.columnSelectedOfDataset) $scope.ngModel.content.columnSelectedOfDataset = {} ; + + if (!$scope.ngModel.content.currentView.center) $scope.ngModel.content.currentView.center = [0,0]; + if (!$scope.ngModel.content.mapId){ + $scope.ngModel.content.mapId = 'map-' + $scope.ngModel.id; + } + + var currLayers = $scope.ngModel.content.layers; + for (l in currLayers){ + var currLayer = currLayers[l]; + var currDsId = currLayer.dsId; + var isCluster = $scope.isCluster(currLayer); + var isHeatmap = $scope.isHeatmap(currLayer); + + // set default indicator (first one) for each layer + var columns = $scope.getColumnSelectedOfDataset(currDsId); + for (var c in columns){ + if (columns[c].properties && columns[c].properties.showMap){ + currLayer.defaultIndicator = columns[c].name; + break; + } } - //set default indicator (first one) for each layer - for (l in $scope.ngModel.content.layers){ - var columns = $scope.getColumnSelectedOfDataset($scope.ngModel.content.layers[l].dsId); - for ( c in columns){ - if (columns[c].properties.showMap){ - $scope.ngModel.content.layers[l].defaultIndicator = columns[c].name; - break; + // all attributes that don't have aggregateBy properties need a default value to true + for (var c in columns) { + var currCol = columns[c]; + if (currCol.fieldType == "ATTRIBUTE") { + if (!currCol.properties) { + currCol.properties = {}; + } + if (!currCol.properties.hasOwnProperty("aggregateBy")) { + currCol.properties.aggregateBy = true; } } } - if (!$scope.ngModel.content.hasOwnProperty("enableBaseLayer")) $scope.ngModel.content.enableBaseLayer = true; - resolve('initialized'); - }); + // Set exploded flag for heatmap and cluster + if (isHeatmap || isCluster) { + $scope.exploded[currDsId] = false; + } + } + if (!$scope.ngModel.content.hasOwnProperty("enableBaseLayer")) $scope.ngModel.content.enableBaseLayer = true; } @@ -624,8 +670,8 @@ along with this program. If not, see . if (previousZoom > newZoom ){ for (l in $scope.ngModel.content.layers){ var layerDef = $scope.ngModel.content.layers[l]; - var isCluster = (layerDef.clusterConf && layerDef.clusterConf.enabled) ? true : false; - var isHeatmap = (layerDef.heatmapConf && layerDef.heatmapConf.enabled) ? true : false; + var isCluster = $scope.isCluster(layerDef); + var isHeatmap = $scope.isHeatmap(layerDef); if (isCluster){ var values = $scope.values[layerDef.name]; $scope.createLayerWithData(layerDef.name, values, true, false); //return to cluster view @@ -700,17 +746,30 @@ along with this program. If not, see . }); - $scope.map.on('dblclick', function(evt) { - for (l in $scope.ngModel.content.layers){ - var layerDef = $scope.ngModel.content.layers[l]; - var isCluster = (layerDef.clusterConf && layerDef.clusterConf.enabled) ? true : false; - var isHeatmap = (layerDef.heatmapConf && layerDef.heatmapConf.enabled) ? true : false; - if (isCluster || isHeatmap){ - var values = $scope.values[layerDef.name]; - $scope.createLayerWithData(layerDef.name, values, false, false); - } - } - }); + $scope.map.on('dblclick', function(evt) { + var currLayers = $scope.ngModel.content.layers; + for (l in currLayers){ + var layerDef = currLayers[l]; + var dsId = layerDef.dsId; + + var isCluster = $scope.isCluster(layerDef); + var isHeatmap = $scope.isHeatmap(layerDef); + + // Don't recreate the map if it's not needed + if (isCluster || isHeatmap) { + + $scope.exploded[dsId] = !$scope.exploded[dsId]; + + if ($scope.exploded[dsId]) { + var values = $scope.values[layerDef.name]; + $scope.createLayerWithData(layerDef.name, values, false, false); + } else { + var values = $scope.values[layerDef.name]; + $scope.createLayerWithData(layerDef.name, values, isCluster, isHeatmap); + } + } + } + }); // change mouse cursor when over marker $scope.map.on('pointermove', function(e) { @@ -741,11 +800,17 @@ along with this program. If not, see . var geoColumn = null; var selectedMeasure = null; var columnsForData = []; - var isCluster = (layerDef.clusterConf && layerDef.clusterConf.enabled) ? true : false; - var isHeatmap = (layerDef.heatmapConf && layerDef.heatmapConf.enabled) ? true : false; + var isCluster = $scope.isCluster(layerDef); + var isHeatmap = $scope.isHeatmap(layerDef); columnsForData = $scope.getColumnSelectedOfDataset(layerDef.dsId) || []; + // exclude from model all attributes that are not needed for aggregation + columnsForData = columnsForData.filter(function(el) { + var type = el.fieldType; + return !(type == "ATTRIBUTE" && !el.properties.aggregateBy); + }); + for (f in columnsForData){ var tmpField = columnsForData[f]; if (tmpField.fieldType == "SPATIAL_ATTRIBUTE") { @@ -759,7 +824,8 @@ along with this program. If not, see . } - var model = {content: {columnSelectedOfDataset: columnsForData }}; + var model = { content: { columnSelectedOfDataset: columnsForData }, updateble: true }; + if($scope.ngModel.filters) model.filters = $scope.ngModel.filters; var features = []; var layer = new ol.layer.Vector(); @@ -769,6 +835,10 @@ along with this program. If not, see . $scope.createLayerWithData(layerDef.name, allDatasetRecords, isCluster, isHeatmap); $scope.hideWidgetSpinner(); + + $scope.map.render(); + // Seams to fix invisible layer problem before the first map interaction + $scope.map.updateSize(); },function(error){ console.log("Error loading dataset with id [ "+layerDef.dsId+"] "); sbiModule_messaging.showInfoMessage($scope.translate.load('sbi.cockpit.map.datasetLoadingError').replace("{0}",layerDef.dsId), 'Title', 3000); @@ -781,75 +851,59 @@ along with this program. If not, see . $scope.createMap = function (){ - $scope.initializeTemplate().then(function(){ - - var layers = []; - - if ($scope.needsBaseLayer()) { - layers.push($scope.createBaseLayer()); - } + var layers = []; - if ($scope.needsBackgroundLayer()) { - layers.push($scope.createBackgroundLayer()); - } + if (!$scope.popupContainer){ + $scope.popupContainer = document.getElementById('popup-' + $scope.ngModel.id); + $scope.closer = document.getElementById('popup-closer-' +$scope.ngModel.id); + } - if (!$scope.popupContainer){ - $scope.popupContainer = document.getElementById('popup-' + $scope.ngModel.id); - $scope.closer = document.getElementById('popup-closer-' +$scope.ngModel.id); + //create overlayers (popup..) + var overlay = new ol.Overlay({ + element: $scope.popupContainer, + autoPan: true, + autoPanAnimation: { + duration: 250 } + }); - //create overlayers (popup..) - var overlay = new ol.Overlay({ - element: $scope.popupContainer, - autoPan: true, - autoPanAnimation: { - duration: 250 - } - }); - - //setting coordinates (from the first layer if they aren't set into the template) - if ($scope.ngModel.content.currentView.center[0] == 0 && $scope.ngModel.content.currentView.center[1] == 0 && $scope.layers.length > 0){ - var tmpLayer = $scope.layers[0].layer; - cockpitModule_mapServices.updateCoordinatesAndZoom($scope.ngModel, $scope.map, tmpLayer, false); - } + //setting coordinates (from the first layer if they aren't set into the template) + if ($scope.ngModel.content.currentView.center[0] == 0 && $scope.ngModel.content.currentView.center[1] == 0 && $scope.layers.length > 0){ + var tmpLayer = $scope.layers[0].layer; + cockpitModule_mapServices.updateCoordinatesAndZoom($scope.ngModel, $scope.map, tmpLayer, false); + } - $scope.map = new ol.Map({ - target: 'map-' + $scope.ngModel.id, - layers: layers, - overlays: [overlay], - view: new ol.View({ - center: $scope.ngModel.content.currentView.center, - zoom: $scope.ngModel.content.currentView.zoom || 3 - }) - }); - console.log("Created obj map with id [" + 'map-' + $scope.ngModel.id + "]", $scope.map); + $scope.map = new ol.Map({ + target: 'map-' + $scope.ngModel.id, + layers: layers, + overlays: [overlay], + controls: [], + interactions: [ + new ol.interaction.DragPan(), + new ol.interaction.PinchRotate(), + new ol.interaction.PinchZoom() + ] + }); + console.log("Created obj map with id [" + 'map-' + $scope.ngModel.id + "]", $scope.map); -// // get background layer -// $scope.addBackgroundLayer(); + $scope.setZoomControl(); + $scope.setScaleControl(); + $scope.setMouseWheelZoomInteraction(); - //just for refresh - if (!$scope.map.getSize()){ - $scope.map.setSize([cockpitModule_widgetConfigurator.map.initialDimension.width, - cockpitModule_widgetConfigurator.map.initialDimension.height]); - }else{ - $scope.map.setSize($scope.map.getSize()); - } + $scope.setMapView(); - $scope.map.renderSync(); + //just for refresh + $scope.setMapSize(); - //add events methods - $scope.addViewEvents(); - $scope.addMapEvents(overlay); - $scope.loading = false; - $timeout(function(){ - $scope.widgetIsInit=true; - cockpitModule_properties.INITIALIZED_WIDGETS.push($scope.ngModel.id); - },1500); + //add events methods + $scope.addViewEvents(); + $scope.addMapEvents(overlay); + $scope.loading = false; + $timeout(function(){ + $scope.widgetIsInit=true; + cockpitModule_properties.INITIALIZED_WIDGETS.push($scope.ngModel.id); + },1500); - }).then(function() { - $scope.addAllLayers(); - $scope.map.renderSync(); - }); } //control panel events @@ -962,15 +1016,17 @@ along with this program. If not, see . } } - $scope.clearInternalData = function(){ - $scope.layers = []; - $scope.values = {}; - $scope.savedValues = {}; + $scope.clearInternalData = function(){ + $scope.layers = []; + $scope.values = {}; + $scope.savedValues = {}; $scope.configs = {}; $scope.legend = []; + $scope.exploded = {}; + $scope.layerVisibility = []; cockpitModule_mapThematizerServices.removeLegends(); - - } + cockpitModule_mapThematizerServices.clearDefaultMarkerCache(); + } $scope.setLayerProperty = function(l, p, v){ for (o in $scope.layers){ @@ -1104,7 +1160,9 @@ along with this program. If not, see . var layers = $scope.ngModel.content.layers; for (var currLayerIdx in layers) { var currLayer = layers[currLayerIdx]; - dsIds.push(currLayer.dsId); + if (!$scope.isFilterDisabled(currLayer)) { + dsIds.push(currLayer.dsId); + } } } @@ -1336,6 +1394,129 @@ along with this program. If not, see . $scope.filterLayerBy(currLayer) } + $scope.getPropValue = function(prop) { + var currProp = $scope.props[prop.name]; + var currPropValue = currProp.value; + var ret = ""; + if (prop.style) { + var style = prop.style; + var prefix = style.prefix; + var suffix = style.suffix; + var precision = style.precision; + var asString = style.asString; + + if (asString == undefined) { + asString = false; + } + if (precision == undefined) { + precision = 0; + } + + if (prefix != undefined) { + ret += "" + prefix + ""; + } + + if (asString) { + ret += currPropValue; + } else { + ret += isNaN(currPropValue) ? currPropValue : $filter("number")(currPropValue, precision); + } + + if (suffix != undefined) { + ret += "" + suffix; + } + + } else { + ret = currPropValue; + } + return ret; + } + + $scope.isFilterDisabled = function(layerDef) { + var dsId = layerDef.dsId; + var isCluster = $scope.isCluster(layerDef); + var isHeatmap = $scope.isHeatmap(layerDef); + var isExploded = $scope.exploded.hasOwnProperty(dsId) ? $scope.exploded[dsId] : true; + + return (isCluster || isHeatmap) && !isExploded; + } + + $scope.isHeatmap = function(layerDef) { + return (layerDef.heatmapConf && layerDef.heatmapConf.enabled) ? true : false; + } + + $scope.isCluster = function(layerDef) { + return (layerDef.clusterConf && layerDef.clusterConf.enabled) ? true : false; + } + + $scope.setMapView = function() { + var newView = new ol.View({ + center: $scope.ngModel.content.currentView.center, + zoom: $scope.ngModel.content.currentView.zoom || 3 + }); + + $scope.map.setView(newView); + } + + $scope.getZoomFactor = function() { + return ($scope.ngModel.content.zoomFactor || 1); + } + + $scope.createZoomControl = function() { + var delta = $scope.getZoomFactor(); + + return new ol.control.Zoom({ + delta: delta + }); + } + + $scope.createScaleControl = function() { + return new ol.control.ScaleLine(); + } + + $scope.createMouseWheelZoomInteraction = function() { + var delta = $scope.getZoomFactor(); + + return new ol.interaction.MouseWheelZoom({ + maxDelta: delta + }); + } + + $scope.setZoomControl = function() { + + if (!(typeof $scope.zoomControl == "undefined")) { + $scope.map.removeControl($scope.zoomControl); + } + + $scope.zoomControl = $scope.createZoomControl(); + + $scope.map.addControl($scope.zoomControl); + } + + $scope.setScaleControl = function() { + + if (!(typeof $scope.scaleControl == "undefined")) { + $scope.map.removeControl($scope.scaleControl); + } + + if ($scope.ngModel.content.showScale) { + $scope.scaleControl = $scope.createScaleControl(); + + $scope.map.addControl($scope.scaleControl); + } else { + $scope.scaleControl = undefined; + } + } + + $scope.setMouseWheelZoomInteraction = function() { + + $scope.map.removeInteraction($scope.mouseWheelZoomInteraction); + + $scope.mouseWheelZoomInteraction = $scope.createMouseWheelZoomInteraction(); + + $scope.map.addInteraction($scope.mouseWheelZoomInteraction); + } + // $scope.reinit(); // In edit mode, if a remove dataset from cokpit it has to be deleted also from widget diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidgetEdit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidgetEdit.js index 0f6bdf9819b..33100586bb3 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidgetEdit.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/mapWidgetEdit.js @@ -140,7 +140,7 @@ function mapWidgetEditControllerFunction( layer.hasShownDetails = false; var columnsList = layer.content.columnSelectedOfDataset; for(var i in columnsList){ - if(columnsList[i].properties.showDetails){ + if(columnsList[i].properties && columnsList[i].properties.showDetails){ layer.hasShownDetails = true; return; } @@ -227,9 +227,30 @@ function mapWidgetEditControllerFunction( newLayer.dataset.dsId = tempLayer.id.dsId; for(var i in tempLayer.metadata.fieldsMeta){ - tempLayer.metadata.fieldsMeta[i].aliasToShow = tempLayer.metadata.fieldsMeta[i].alias; - columnSelected.push(tempLayer.metadata.fieldsMeta[i]); + var currCol = tempLayer.metadata.fieldsMeta[i]; + currCol.aliasToShow = currCol.alias; + + // Initialize columns + if (currCol.fieldType == 'ATTRIBUTE') { + currCol.properties.aggregateBy = true; + } + + columnSelected.push(currCol); } + // The spatial attribute must be the first attribute + // when all the logics for the aggregations will take + // place. + columnSelected.sort(function(el1, el2) { + + if (el1.fieldType == 'SPATIAL_ATTRIBUTE') { + return -1; + } else if (el2.fieldType == 'SPATIAL_ATTRIBUTE') { + return +1; + } else { + return 0; + } + + }); $scope.newModel.content.layers.push(newLayer); var availableDatasets = cockpitModule_datasetServices.getAvaiableDatasets(); var exists = false; @@ -504,6 +525,65 @@ function mapWidgetEditControllerFunction( return column.isCalculated || !$scope.checkDs(column,false); } + $scope.setAggregateBy = function(column,layer) { + if (!column.properties.aggregateBy) { + column.properties.showDetails = false; + column.properties.showFilter = false; + column.properties.modal = false; + } + } + + $scope.setColumnStyle = function(event,column) { + + $mdDialog.show({ + templateUrl: baseScriptPath+ '/directives/cockpit-columns-configurator/templates/cockpitColumnStyle.html', + parent : angular.element(document.body), + clickOutsideToClose:true, + escapeToClose :true, + preserveScope: false, + autoWrap:false, + fullscreen: true, + locals: { + model: $scope.newModel, + selectedColumn: column, + dialogOptions: { + needsCommonPrefs: false, + needsVisualization: false, + needsThresholds: false, + needsFormat: true, + needsStyle: false, + needsTooltip: false + } + }, + controller: cockpitStyleColumnFunction + }).then(function(answer) { + console.log("Selected column:", column); + }, function() { + console.log("Selected column:", column); + }); + + } + + $scope.needsBorderColor = function(layer) { + return layer.content + .columnSelectedOfDataset + .find(function(e) { + return e.fieldType == "SPATIAL_ATTRIBUTE"; + }) + .properties + .coordType != "string"; + } + + $scope.changeCoordType = function(layer) { + if (!$scope.needsBorderColor(layer)) { + $scope.resetBorderColor(layer); + } + } + + $scope.resetBorderColor = function(layer) { + layer.markerConf.style.borderColor = undefined; + } + function loadAvailableLayers() { sbiModule_restServices.restToRootProject(); sbiModule_restServices.get(".", "layers") diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetControlPanel.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetControlPanel.html index 01c1769c0d7..9899c223ef7 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetControlPanel.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetControlPanel.html @@ -4,6 +4,10 @@

{{translate.load('sbi.cockpit.map.section.options')}}

+ + {{::translate.load('sbi.general.close')}} + +
@@ -61,37 +65,38 @@

{{translate.load('sbi.cockpit.map.section.options')

{{translate.load('sbi.cockpit.map.section.filters')}}

-
+
+
- {{currLayer.alias}}{{currLayer.alias}} + {{currLayer.alias}}{{currLayer.alias}} {{isFilterDisabled(currLayer)}}
- - - - - - -
-
{{value}},
-
-
+ + + - + + +
+
{{value}},
+
+
-
+
+ +
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetEditPropertyTemplate.html index 43207dbd810..07a815ea706 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetEditPropertyTemplate.html @@ -17,7 +17,7 @@

Map widget configuration

-

{{translate.load('sbi.cockpit.map.backgroundLayers')}}

+

{{translate.load('sbi.cockpit.map.genericConfiguration')}}

@@ -30,6 +30,22 @@

{{translate.load('sbi.cockpit.map.backgroundLayers')}}

{{ layer.value }} + + + + 10% + 20% + 30% + 40% + 50% + 60% + 70% + 80% + 90% + 100% + + + {{translate.load('sbi.cockpit.map.showScale')}}
@@ -49,6 +65,10 @@

{{translate.load('sbi.cockpit.map.backgroundLayers')}}

+ + + + diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetMetadata.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetMetadata.html index 34aaa40db9d..2da5b484e65 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetMetadata.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetMetadata.html @@ -24,7 +24,7 @@

{{layer.expanded}}

{{column.name}} - + string JSON WKT Format @@ -65,6 +65,7 @@

{{layer.expanded}}

{{translate.load('sbi.cockpit.map.edit.metadata.alias')}} {{translate.load('sbi.cockpit.map.edit.metadata.type')}} {{translate.load('sbi.cockpit.map.edit.metadata.aggregationFunction')}} + {{translate.load('sbi.cockpit.map.edit.metadata.aggregateBy')}} {{translate.load('sbi.cockpit.map.edit.metadata.showOnDetail')}} {{translate.load('sbi.cockpit.map.edit.metadata.showOnMap')}} {{translate.load('sbi.cockpit.map.edit.metadata.showOnFilter')}} @@ -101,13 +102,16 @@

{{layer.expanded}}

- + + + + - + @@ -120,17 +124,23 @@

{{layer.expanded}}

- - + + {{translate.load('sbi.cockpit.map.edit.metadata.threshold')}} - + + + + {{translate.load('sbi.cockpit.map.edit.metadata.style')}} + + + - + {{translate.load('sbi.cockpit.map.edit.metadata.delete')}} diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetTemplate.html index 3c86b25c467..f79cb4d781e 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetTemplate.html @@ -1,33 +1,33 @@
-
-
- {{translate.load('sbi.cockpit.map.togglemapoptions')}} - -
- -
- - + - +
\ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetVisualizations.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetVisualizations.html index 199d56496f5..19cd9d9fd9b 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetVisualizations.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/mapWidget/templates/mapWidgetVisualizations.html @@ -2,7 +2,7 @@
-

Visualization types

+

{{translate.load('sbi.cockpit.map.edit.visualization.cardName')}}

@@ -14,115 +14,120 @@

Visualization types

- Clusters + {{translate.load('sbi.cockpit.map.edit.visualization.header.clusters')}}
- + - + - + - +
- +
10
- Analysis + {{translate.load('sbi.cockpit.map.edit.visualization.header.choroplet')}}
- - - Classify by equal intervals - Classify by quantils - + + + {{translate.load('sbi.cockpit.map.edit.visualization.choroplet.classesByEqualIntervals')}} + {{translate.load('sbi.cockpit.map.edit.visualization.choroplet.classesByQuantils')}} + - +
- + - +
- Markers + {{translate.load('sbi.cockpit.map.edit.visualization.header.marker')}}
- Default marker + {{translate.load('sbi.cockpit.map.edit.visualization.marker.defaultMarker')}}
- Icon marker + {{translate.load('sbi.cockpit.map.edit.visualization.marker.iconMarker')}}
- Image Marker + {{translate.load('sbi.cockpit.map.edit.visualization.marker.imageMarker')}}
- Image from web marker + {{translate.load('sbi.cockpit.map.edit.visualization.marker.markerFromUrl')}}
- - - - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + + + - - - - - - - - - + + + + + + + + +
- + @@ -132,16 +137,16 @@

Visualization types

- Heatmap settings + {{translate.load('sbi.cockpit.map.edit.visualization.header.heatmap')}}
- + - +
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidget.js index cfcfa8b930f..6d2bc038072 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidget.js @@ -125,12 +125,13 @@ along with this program. If not, see . document.getElementById(iframe.id).contentWindow.document.close(); } - $scope.buildAggregations = function (meta, dataset_label) { + $scope.buildAggregations = function (columnSelectedOfDataset, dataset_label) { aggregations = {"measures": [], "categories": [], "dataset": dataset_label}; - for (i=0; i. $scope.setPythonParameters = function () { //get user_id from parameters and use it for authentication in python - url_string = window.location.href - url = new URL(url_string); $scope.encodedUserId = sbiModule_user.userUniqueIdentifier; $scope.drivers = cockpitModule_analyticalDrivers; //if there is a dataset selected save its label @@ -161,7 +160,7 @@ along with this program. If not, see . $scope.dataset = cockpitModule_datasetServices.getDatasetById($scope.ngModel.dataset.dsId); $scope.selections = cockpitModule_datasetServices.getWidgetSelectionsAndFilters($scope.ngModel, $scope.dataset); $scope.dataset_label = $scope.dataset.label; - $scope.aggregations = $scope.buildAggregations($scope.dataset.metadata.fieldsMeta, $scope.dataset_label); + $scope.aggregations = $scope.buildAggregations($scope.ngModel.content.columnSelectedOfDataset, $scope.dataset_label); $scope.parameters = cockpitModule_datasetServices.getDatasetParameters($scope.ngModel.dataset.dsId); } else { //no dataset selected diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidgetEdit.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidgetEdit.js index 1f6381485a9..892e73c5df5 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidgetEdit.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/pythonWidgetEdit.js @@ -27,6 +27,7 @@ angular function pythonWidgetEditControllerFunction( $scope, $http, + $mdToast, finishEdit, model, sbiModule_translate, @@ -35,6 +36,7 @@ function pythonWidgetEditControllerFunction( cockpitModule_datasetServices, cockpitModule_analyticalDrivers, cockpitModule_helperDescriptors, + cockpitModule_generalOptions, sbiModule_restServices) { $scope.translate = sbiModule_translate; @@ -102,9 +104,17 @@ function pythonWidgetEditControllerFunction( for(var d in $scope.availableDatasets){ if($scope.availableDatasets[d].id.dsId == newValue) dsIndex = d; } - if(!newValue || typeof dsIndex != 'undefined'){ + if(typeof dsIndex != 'undefined'){ $scope.dataset = $scope.availableDatasets[dsIndex]; - $scope.newModel.content.columnSelectedOfDataset = $scope.dataset.metadata.fieldsMeta; + if (newValue != oldValue) $scope.newModel.content.columnSelectedOfDataset = $scope.dataset.metadata.fieldsMeta; + for (i in $scope.newModel.content.columnSelectedOfDataset) { + obj = $scope.newModel.content.columnSelectedOfDataset[i]; + if(obj.fieldType == "MEASURE" && !obj.value) obj.aggregationSelected = "SUM"; + } + if ($scope.columnsGrid && $scope.columnsGrid.api) { + $scope.columnsGrid.api.setRowData($scope.newModel.content.columnSelectedOfDataset); + resizeColumns(); + } } }else{ if($scope.newModel.content && $scope.newModel.content.columnSelectedOfDataset) $scope.newModel.content.columnSelectedOfDataset = []; @@ -152,6 +162,18 @@ function pythonWidgetEditControllerFunction( }; $scope.saveConfiguration = function () { + if(!$scope.checkDataset()){ + $scope.showAction($scope.translate.load('kn.cockpit.python.errordataset')); + return; + } + if(!$scope.checkAliases()){ + $scope.showAction($scope.translate.load('sbi.cockpit.table.erroraliases')); + return; + } + if(!$scope.checkEnvironment()){ + $scope.showAction($scope.translate.load('kn.cockpit.python.errorenvironment')); + return; + } mdPanelRef.close(); angular.copy($scope.newModel,model); $scope.$destroy(); @@ -164,4 +186,209 @@ function pythonWidgetEditControllerFunction( finishEdit.reject(); }; + // aggregations on dataset + + if (!$scope.newModel.settings) $scope.newModel.settings = {}; + if (!$scope.newModel.content) $scope.newModel.content = {name: $scope.newModel.type + '_' + $scope.newModel.id}; + $scope.availableAggregations = ["NONE","SUM","AVG","MAX","MIN","COUNT","COUNT_DISTINCT"]; + + if($scope.newModel.dataset && $scope.newModel.dataset.dsId){ + $scope.local = cockpitModule_datasetServices.getDatasetById($scope.newModel.dataset.dsId); + } + + $scope.showCircularcolumns = {value :false}; + + $scope.colorPickerProperty={format:'rgb'} + + $scope.columnsGrid = { + angularCompileRows: true, + domLayout :'autoHeight', + enableColResize: false, + enableFilter: false, + enableSorting: false, + onGridReady : resizeColumns, + onCellEditingStopped: refreshRow, + singleClickEdit: true, + columnDefs: [ + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.name'), field:'name'}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.alias'), field:'alias',"editable":true,cellRenderer:editableCell, cellClass: 'editableCell'}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.type'), field: 'fieldType'}, + {headerName: $scope.translate.load('sbi.cockpit.widgets.table.column.aggregation'), field: 'aggregationSelected', cellRenderer: aggregationRenderer,"editable":isAggregationEditable, cellClass: 'editableCell', + cellEditor:"agSelectCellEditor",cellEditorParams: {values: $scope.availableAggregations}}, + {headerName:"",cellRenderer: buttonRenderer,"field":"valueId","cellStyle":{"border":"none !important","text-align": "right","display":"inline-flex","justify-content":"flex-end"},width: 150,suppressSizeToFit:true, tooltip: false}], + rowData: $scope.newModel.content.columnSelectedOfDataset + } + + function resizeColumns(){ + $scope.columnsGrid.api.sizeColumnsToFit(); + } + + function editableCell(params){ + return typeof(params.value) !== 'undefined' ? ' '+params.value+''+params.value+'' : ''; + } + function isInputEditable(params) { + return typeof(params.data.name) !== 'undefined'; + } + function isAggregationEditable(params) { + if (params.data.isCalculated) return false; + return params.data.fieldType == "MEASURE" ? true : false; + } + + function aggregationRenderer(params) { + var aggregation = ' '+params.value+''; + if (!params.data.isCalculated && params.data.fieldType == "MEASURE") { + return aggregation; + } else return ""; + } + + function buttonRenderer(params){ + var calculator = ''; + if(params.data.isCalculated){ + calculator = ''; + } + return calculator + '{{::translate.load("sbi.cockpit.widgets.table.column.delete")}}'; + } + + function refreshRow(cell){ + $scope.columnsGrid.api.redrawRows({rowNodes: [$scope.columnsGrid.api.getDisplayedRowAtIndex(cell.rowIndex)]}); + } + + $scope.deleteColumn = function(rowName,event) { + for(var k in $scope.newModel.content.columnSelectedOfDataset){ + if($scope.newModel.content.columnSelectedOfDataset[k].name == rowName) var item = $scope.newModel.content.columnSelectedOfDataset[k]; + } + var index=$scope.newModel.content.columnSelectedOfDataset.indexOf(item); + $scope.newModel.content.columnSelectedOfDataset.splice(index,1); + } + + $scope.checkEnvironment = function(){ + if (!$scope.newModel.pythonAddress) return false; + else return true; + } + + $scope.checkDataset = function(){ + if (!$scope.newModel.dataset || !$scope.newModel.dataset.dsId) return false; + else return true; + } + + $scope.checkAliases = function(){ + var columns = $scope.newModel.content.columnSelectedOfDataset; + for(var i = 0; i < columns.length - 1; i++){ + for(var j = i + 1; j < columns.length; j++){ + if(columns[i].alias == columns[j].alias){ + return false; + } + } + } + return true; + } + + $scope.$watchCollection('newModel.content.columnSelectedOfDataset',function(newValue,oldValue){ + if($scope.columnsGrid.api && newValue){ + $scope.columnsGrid.api.setRowData(newValue); + $scope.columnsGrid.api.sizeColumnsToFit(); + } + }) + + $scope.openListColumn = function(){ + if($scope.newModel.dataset == undefined || $scope.newModel.dataset.dsId == undefined){ + $scope.showAction($scope.translate.load("sbi.cockpit.table.missingdataset")); + }else{ + $mdDialog.show({ + templateUrl: baseScriptPath+ '/directives/cockpit-columns-configurator/templates/cockpitColumnsOfDataset.html', + parent : angular.element(document.body), + clickOutsideToClose:true, + escapeToClose :true, + preserveScope: true, + autoWrap:false, + locals: {model:$scope.newModel, getMetadata : $scope.getMetadata}, + fullscreen: true, + controller: addColumnController + }).then(function(returnModel) { + $scope.newModel.content.columnSelectedOfDataset = returnModel; + }, function() { + }); + } + } + + $scope.showAction = function(text) { + var toast = $mdToast.simple() + .content(text) + .action('OK') + .highlightAction(false) + .hideDelay(3000) + .position('top') + + $mdToast.show(toast).then(function(response) { + + if ( response == 'ok' ) { + + + } + }); + } + } + + +function addColumnController($scope,sbiModule_translate,$mdDialog,model,getMetadata,cockpitModule_datasetServices,cockpitModule_generalOptions){ + $scope.translate=sbiModule_translate; + $scope.model = angular.copy(model); + $scope.columnSelected = []; + $scope.localDataset = {}; + if($scope.model.dataset && $scope.model.dataset.dsId){ + angular.copy(cockpitModule_datasetServices.getDatasetById($scope.model.dataset.dsId), $scope.localDataset); + } else{ + $scope.model.dataset= {}; + angular.copy([], $scope.model.dataset.metadata.fieldsMeta); + } + + $scope.filterColumns = function(){ + var tempColumnsList = $filter('filter')($scope.localDataset.metadata.fieldsMeta,$scope.columnsSearchText); + $scope.columnsGridOptions.api.setRowData(tempColumnsList); + } + + $scope.columnsGridOptions = { + enableColResize: false, + enableFilter: true, + enableSorting: true, + pagination: true, + paginationAutoPageSize: true, + onGridSizeChanged: resizeColumns, + rowSelection: 'multiple', + rowMultiSelectWithClick: true, + defaultColDef: { + suppressMovable: true, + tooltip: function (params) { + return params.value; + }, + }, + columnDefs :[{"headerName":"Column","field":"alias",headerCheckboxSelection: true, checkboxSelection: true}, + {"headerName":"Field Type","field":"fieldType"}, + {"headerName":"Type","field":"type"}], + rowData : $scope.localDataset.metadata.fieldsMeta + }; + + function resizeColumns(){ + $scope.columnsGridOptions.api.sizeColumnsToFit(); + } + + $scope.saveColumnConfiguration=function(){ + if($scope.model.content.columnSelectedOfDataset == undefined){ + $scope.model.content.columnSelectedOfDataset = []; + } + + for(var i in $scope.columnsGridOptions.api.getSelectedRows()){ + var obj = $scope.columnsGridOptions.api.getSelectedRows()[i]; + obj.aggregationSelected = 'SUM'; + obj.typeSelected = obj.type; + $scope.model.content.columnSelectedOfDataset.push(obj); + } + $mdDialog.hide($scope.model.content.columnSelectedOfDataset); + } + + $scope.cancelConfiguration=function(){ + $mdDialog.cancel(); + } + +} \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/templates/pythonWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/templates/pythonWidgetEditPropertyTemplate.html index 56db148d394..f095e9135c6 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/templates/pythonWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/pythonWidget/templates/pythonWidgetEditPropertyTemplate.html @@ -10,15 +10,33 @@

{{translate.load('kn.cockpit.python.configuration')}}

+ + - - - - - + + + + + + + + +
+ {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.tablecolumns')}} + + {{translate.load('sbi.cockpit.widgets.table.tabledesignerpanel.tableoptions.addcolumn')}} + +
+
+
+ +
+
+
+
- + @@ -90,7 +108,7 @@

{{translate.load('kn.cockpit.python.availabletags') - + diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/selectorWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/selectorWidget.js index 890361ae45f..2a849531bee 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/selectorWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/selectorWidget.js @@ -49,6 +49,7 @@ along with this program. If not, see . $interval, $mdPanel, $q, + $sce, $filter, sbiModule_translate, sbiModule_restServices, @@ -65,7 +66,7 @@ along with this program. If not, see . $rootScope){ $scope.getTemplateUrl = function(template){ - return cockpitModule_generalServices.getTemplateUrl('selectorWidget',template); + return $sce.trustAsResourceUrl(cockpitModule_generalServices.getTemplateUrl('selectorWidget',template)); } if(!$scope.ngModel.settings) $scope.ngModel.settings = {}; @@ -85,6 +86,13 @@ along with this program. If not, see . $scope.isSelected = function(p){ return $scope.selectedValues && $scope.selectedValues.indexOf(p) > -1; } + + $scope.isSelectedColumnTemporal = function(){ + if($scope.ngModel.content.selectedColumn){ + var datesFormat = ['java.sql.Date','java.util.Date','java.sql.Timestamp','oracle.sql.TIMESTAMP']; + return (datesFormat.indexOf($scope.ngModel.content.selectedColumn.type) != -1); + }else return false; + } $scope.mapToColumn = function(x){ return x.column_1; @@ -101,6 +109,22 @@ along with this program. If not, see . else $scope.prepareParameter(getValueFromString(e.target.parentNode.attributes.value.value)); } } + + $scope.selectDate = function(){ + var tempDates = []; + if($scope.ngModel.settings.modalityValue=='multiValue'){ + if(!$scope.startDate || !$scope.endDate) return; + var from = $scope.startDate.getTime(); + var to = $scope.endDate.getTime(); + var values = $scope.ngModel.activeValues || $scope.datasetRecords.rows; + for(var k in values){ + var value = values[k].column_1 || values[k]; + var dateToCheck = new Date(value).getTime(); + if(dateToCheck >= from && dateToCheck <= to) tempDates.push(value); + } + }else tempDates.push($filter('date')($scope.startDate,'dd/MM/yyyy HH:mm:ss.sss')); + $scope.toggleParameter(tempDates); + } var getValueFromString = function(s){ for(i in $scope.datasetRecords.rows){ @@ -144,6 +168,7 @@ along with this program. If not, see . $scope.datasetRecords = {}; $scope.cockpitModule_widgetSelection = cockpitModule_widgetSelection; $scope.realTimeSelections = cockpitModule_widgetServices.realtimeSelections; + // set a watcher on a variable that can contains the associative selections for realtime dataset var realtimeSelectionsWatcher = $scope.$watchCollection('realTimeSelections',function(newValue,oldValue,scope){ @@ -181,13 +206,6 @@ along with this program. If not, see . if(!$scope.ngModel.style){ $scope.ngModel.style={}; } - if(!$scope.ngModel.settings.summary){ - $scope.ngModel.settings.summary={ - 'enabled': false, - 'forceDisabled': false, - 'style': {} - }; - } $scope.init=function(element,width,height){ $scope.refreshWidget(null, 'init'); @@ -198,6 +216,9 @@ along with this program. If not, see . $scope.showUnlock = false; $scope.showWidgetSpinner(); $scope.ngModel.activeValues = null; + + if($scope.ngModel.settings.defaultStartDate) $scope.ngModel.settings.defaultStartDate = new Date($scope.ngModel.settings.defaultStartDate); + if($scope.ngModel.settings.defaultEndDate) $scope.ngModel.settings.defaultEndDate = new Date($scope.ngModel.settings.defaultEndDate); if(!$scope.ngModel.dataset.label){ $scope.ngModel.dataset.label = cockpitModule_datasetServices.getDatasetById($scope.ngModel.dataset.dsId).label; @@ -443,7 +464,8 @@ along with this program. If not, see . applyDefaultValues = true; break; case 'STATIC': - $scope.defaultValues = $scope.ngModel.settings.staticValues.split(","); + if($scope.ngModel.settings.staticValues) $scope.defaultValues = $scope.ngModel.settings.staticValues.split(","); + else $scope.defaultValues.push(''); applyDefaultValues = true; break; } @@ -598,7 +620,7 @@ along with this program. If not, see . } }else{ // COMBOBOX - if(parVal && parVal.length>0){ + if(parVal && parVal.length>0){ $scope.doSelection($scope.ngModel.content.selectedColumn.aliasToShow, angular.copy(parVal)); }else{ item.value=angular.copy(parVal); @@ -610,7 +632,11 @@ along with this program. If not, see . } $scope.getOptions = function(){ - var isSortinEnabled = $scope.ngModel.content.sortingOrder && $scope.ngModel.content.sortingOrder!=''; + var isSortinEnabled = false; + if($scope.ngModel.content.sortingOrder){ + if($scope.ngModel.content.sortingOrder === '') isSortinEnabled = false; + else isSortinEnabled = true; + } var obj = {}; obj["page"] = -1; @@ -630,6 +656,10 @@ along with this program. If not, see . } $scope.deleteSelections(tempItem); } + + $scope.clearStartDate = function(){ + $scope.startDate = ''; + } $scope.deleteSelections = function(item){ var reloadAss=false; @@ -728,6 +758,28 @@ along with this program. If not, see . $scope.model = {}; angular.copy(originalModel,$scope.model); + $scope.tempSelectedColumn = $scope.model.content.selectedColumn && $scope.model.content.selectedColumn.alias; + + $scope.changeColumn = function(){ + for(var k in $scope.model.content.columnSelectedOfDataset){ + if($scope.model.content.columnSelectedOfDataset[k].alias == $scope.tempSelectedColumn){ + $scope.model.content.selectedColumn = $scope.model.content.columnSelectedOfDataset[k]; + break; + } + } + } + + $scope.$watch('model.content.selectedColumn',function(newValue,oldValue){ + if(newValue){ + $scope.model.settings.sortingColumn = newValue.name; + } + }) + + $scope.$watch('model.content.sortingOrder',function(newValue,oldValue){ + if(newValue){ + $scope.model.settings.sortingOrder = newValue; + } + }) $scope.saveConfiguration=function(){ if($scope.model.dataset == undefined || $scope.model.dataset.dsId == undefined ){ @@ -739,6 +791,11 @@ along with this program. If not, see . $scope.showAction($scope.translate.load('sbi.cockpit.table.nocolumns')); return; } + + if($scope.model.settings.defaultValue=='STATIC' && !$scope.model.settings.staticValues){ + $scope.showAction($scope.translate.load('sbi.cockpit.table.nodefault')); + return; + } if($scope.model.content.columnSelectedOfDataset == undefined || $scope.model.content.columnSelectedOfDataset.length==0){ $scope.showAction($scope.translate.load('sbi.cockpit.table.nocolumns')); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetEditPropertyTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetEditPropertyTemplate.html index 478614afc30..7bd0064f0d9 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetEditPropertyTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetEditPropertyTemplate.html @@ -13,7 +13,7 @@

{{::translate.format(translate.load('sbi.cockpit.widget.configuration'),tran - +

Label

diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetMultiSelectDialogTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetMultiSelectDialogTemplate.html index 664a8844373..2add2591b5c 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetMultiSelectDialogTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetMultiSelectDialogTemplate.html @@ -26,6 +26,7 @@

{{title || targetColumn.name}}

{{ item.name }}

+ {{ item.name }}
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetTemplate.html b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetTemplate.html index 088cc5c92ed..915591c9456 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetTemplate.html +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/selectorWidget/templates/selectorWidgetTemplate.html @@ -60,28 +60,20 @@
-
- +
- - + + + - - - -
- - + + - - - -
diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/staticPivotTableWidget/staticPivotTableWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/staticPivotTableWidget/staticPivotTableWidget.js index 30d36270c86..786d0d1343a 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/staticPivotTableWidget/staticPivotTableWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/staticPivotTableWidget/staticPivotTableWidget.js @@ -173,7 +173,11 @@ function cockpitStaticPivotTableWidgetControllerFunction( $scope.applyI18N(dataToSend); $scope.options = dataToSend; - sbiModule_restServices.promisePost("1.0/crosstab","update",dataToSend).then( + $scope.oldUpdateExecutions = $scope.oldUpdateExecutions || []; + + var newUpdateExecution = sbiModule_restServices.promisePost("1.0/crosstab","update",dataToSend); + $q.all($scope.oldUpdateExecutions).then(function() { + newUpdateExecution.then( function(response){ var fatherElement = angular.element($scope.subCockpitWidget); $scope.subCockpitWidget.html(response.data.htmlTable); @@ -187,8 +191,11 @@ function cockpitStaticPivotTableWidgetControllerFunction( function(response){ sbiModule_restServices.errorHandler(response.data,"Pivot Table Error") $scope.hideWidgetSpinner(); - } - ) + } + ); + }); + + $scope.oldUpdateExecutions.push(newUpdateExecution) if(nature == 'init'){ $timeout(function(){ @@ -504,11 +511,13 @@ function cockpitStaticPivotTableWidgetControllerFunction( dataColumnList=row.querySelectorAll(".dataNoStandardStyle"); //personal user settings } if(dataColumnList.length>0){ - //alternateRow - if ($scope.ngModel.content.style.showAlternateRows){ - if(tmpOddRow && $scope.ngModel.content.style.measuresRow["odd-background-color"]!= ""){ + // alternateRow only if there are not thresholds + if ($scope.ngModel.content.style.showAlternateRows + && angular.element(dataColumnList).css("background-color") == "") { + if (tmpOddRow + && $scope.ngModel.content.style.measuresRow["odd-background-color"] != "") { angular.element(dataColumnList).css("background-color",$scope.ngModel.content.style.measuresRow["odd-background-color"]) - }else if ($scope.ngModel.content.style.measuresRow["even-background-color"]!= ""){ + } else if ($scope.ngModel.content.style.measuresRow["even-background-color"] != "") { angular.element(dataColumnList).css("background-color",$scope.ngModel.content.style.measuresRow["even-background-color"]) } tmpOddRow=!tmpOddRow; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/textWidget/textWidget.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/textWidget/textWidget.js index 940e44e0433..85ea10f62d6 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/textWidget/textWidget.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/cockpit-widget/widget/textWidget/textWidget.js @@ -187,11 +187,13 @@ function cockpitTextWidgetControllerFunction($scope,cockpitModule_widgetConfigur if(dsIdArray != undefined){ // clean datasets $scope.localModel.datasets = {}; + $scope.localModel.dataset = {dsId : []}; for(var i = 0; i< dsIdArray.length; i++){ var dsId = dsIdArray[i]; var ds = cockpitModule_datasetServices.getDatasetById(dsId); if(ds){ + $scope.localModel.dataset.dsId.push(dsId); $scope.localModel.datasets[ds.label] = ds.metadata.fieldsMeta; $scope.localModel.viewDatasetsDett = {}; $scope.localModel.viewDatasetsDett[ds.label] = false; @@ -240,7 +242,7 @@ function cockpitTextWidgetControllerFunction($scope,cockpitModule_widgetConfigur clickOutsideToClose: false, escapeToClose: false, focusOnOpen: true, - preserveScope: true, + preserveScope: false, locals: {finishEdit:finishEdit,model:$scope.ngModel}, }; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedField.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedField.js index 8360f77ffdc..2bf8b0ce632 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedField.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedField.js @@ -16,15 +16,19 @@ along with this program. If not, see . angular.module('cockpitModule').directive('calculatedField',function(){ return{ - template: ''+ - ''+ - '{{::translate.load("sbi.cockpit.widgets.table.inlineCalculatedFields.title")}}', + template: '', replace: true, scope:{ ngModel: "=", selectedItem : "=?", callbackUpdateGrid : "&?", - callbackUpdateAlias : "&?" + callbackUpdateAlias : "&?", + insideMenu : "=?", + additionalInfo: "=?" }, controller: calculatedFieldController, } @@ -63,7 +67,8 @@ along with this program. If not, see . model:$scope.ngModel, actualItem : $scope.currentRow, callbackUpdateGrid: $scope.callbackUpdateGrid, - callbackUpdateAlias: $scope.callbackUpdateAlias + callbackUpdateAlias: $scope.callbackUpdateAlias, + additionalInfo: $scope.additionalInfo }, //fullscreen: true, controller: calculatedFieldDialogController @@ -79,7 +84,6 @@ along with this program. If not, see . $scope.currentRow.formulaEditor = result.formulaEditor; $scope.currentRow.aggregationSelected = result.aggregationSelected; $scope.currentRow.funcSummary = result.funcSummary; - $scope.currentRow.datasetOrTableFlag = result.datasetOrTableFlag; $scope.currentRow.alias = result.alias; }else{ if ($scope.ngModel.content == undefined) { @@ -100,7 +104,7 @@ along with this program. If not, see . } } - function calculatedFieldDialogController($scope,sbiModule_translate,cockpitModule_template,sbiModule_restServices,$mdDialog,$q,promise,model,actualItem,callbackUpdateGrid,callbackUpdateAlias,cockpitModule_datasetServices,cockpitModule_generalOptions,$timeout, cockpitModule_properties){ + function calculatedFieldDialogController($scope,sbiModule_translate,cockpitModule_template,sbiModule_restServices,$mdDialog,$q,promise,model,actualItem,callbackUpdateGrid,callbackUpdateAlias,additionalInfo,cockpitModule_datasetServices,cockpitModule_generalOptions,$timeout, cockpitModule_properties){ $scope.translate=sbiModule_translate; $scope.cockpitModule_generalOptions = cockpitModule_generalOptions; $scope.model = model; @@ -129,10 +133,25 @@ along with this program. If not, see . }) $scope.availableFormulaTypes = []; + + if(additionalInfo && additionalInfo.nullifFunction && additionalInfo.nullifFunction.length > 0) $scope.nullifWarningLabel = additionalInfo.nullifFunction[0]; + angular.forEach($scope.functions, function(value, key) { - if ($scope.availableFormulaTypes.indexOf(value.type) === -1) $scope.availableFormulaTypes.push(value.type); + if(value.type == $scope.translate.load("kn.cockpit.functions.type.functions")){ + if(additionalInfo && additionalInfo.availableFunctions && additionalInfo.availableFunctions.length != 0){ + if ($scope.availableFormulaTypes.indexOf(value.type) === -1) $scope.availableFormulaTypes.push(value.type); + } + }else if ($scope.availableFormulaTypes.indexOf(value.type) === -1) $scope.availableFormulaTypes.push(value.type); }); - + + $scope.checkFormulaAvailability = function(formula){ + if(formula.type == $scope.translate.load("kn.cockpit.functions.type.functions") && additionalInfo){ + if(additionalInfo.availableFunctions.lenght > 0 && additionalInfo.availableFunctions.indexOf(formula.name) === -1) return false; + } + return true; + } + + //codemirror initializer $scope.reloadCodemirror = false; @@ -144,6 +163,14 @@ along with this program. If not, see . _editor.on("beforeChange", function() {}); _editor.on("change", function() {}); }; + + $scope.$watch('calculatedField.formulaEditor', function(newValue,oldValue){ + if(newValue && newValue.match("/") && $scope.nullifWarningLabel){ + $scope.showWarning = $scope.translate.load('kn.cockpit.calculatedfield.validation.division').replace("{0}", $scope.nullifWarningLabel); + }else { + $scope.showWarning = false; + } + }) //codemirror options $scope.editorOptions = { @@ -187,21 +214,22 @@ along with this program. If not, see . return p2 ? cockpitModule_properties.VARIABLES[p1][p2] : cockpitModule_properties.VARIABLES[p1]; }) if(!$scope.calculatedField.formulaEditor) { - $scope.toastifyMsg('warning',$scope.translate.load("kn.cockpit.calculatedfield.validation.error.noformula")); + if(!save) $scope.toastifyMsg('warning',$scope.translate.load("kn.cockpit.calculatedfield.validation.error.noformula")); reject(); return; } $scope.formulaLoading = true; sbiModule_restServices.restToRootProject(); sbiModule_restServices.promisePost('2.0/datasets','validateFormula',{ - "formula": $scope.calculatedField.formula.trim() + "formula": $scope.calculatedField.formula.trim(), + "measuresList" : $scope.measuresList }) .then(function(response){ if(!save) $scope.toastifyMsg('success',$scope.translate.load("kn.cockpit.calculatedfield.validation.success")); $scope.formulaLoading = false; resolve(); },function(response){ - $scope.toastifyMsg('warning',$scope.translate.load(response.data.errors[0].message)); + if(!save) $scope.toastifyMsg('warning',$scope.translate.load(response.data.errors[0].message)); $scope.formulaLoading = false; reject(response.data.errors[0].message); }) @@ -211,13 +239,9 @@ along with this program. If not, see . $scope.addMeasures = function(field) { var text = field.name; - var prefix = $scope.calculatedField.datasetOrTableFlag ? '"' : field.aggregationSelected+'("'; - var suffix = $scope.calculatedField.datasetOrTableFlag ? '"' : '") '; - - if ($scope.isSolrDataset()) { - prefix = '"'; - suffix = '"'; - } + var prefix = '"'; + var suffix = '"'; + $scope._editor.focus(); if ($scope._editor.somethingSelected()) { @@ -252,36 +276,37 @@ along with this program. If not, see . } } else { - for(var i in $scope.model.content.columnSelectedOfDataset){ - var obj = $scope.model.content.columnSelectedOfDataset[i]; - if(obj.fieldType == 'MEASURE' && !obj.isCalculated){ - $scope.measuresList.push(obj); + for(var i in $scope.model.content.columnSelectedOfDataset){ + var obj = $scope.model.content.columnSelectedOfDataset[i]; + if(obj.fieldType == 'MEASURE' && !obj.isCalculated){ + $scope.measuresList.push(obj); + } } } - } $scope.saveColumnConfiguration=function(){ - $scope.validateFormula(true) - .then(function(success){ - if(!$scope.calculatedField.alias){ - $scope.toastifyMsg('warning',$scope.translate.load("kn.cockpit.calculatedfield.validation.error.noalias")); + if($scope.aliasForm.alias.$valid){ + $scope.validateFormula(true) + .then(function(success){ + if(!$scope.calculatedField.alias){ + $scope.toastifyMsg('warning',$scope.translate.load("kn.cockpit.calculatedfield.validation.error.noalias")); + return; + } + $scope.result = angular.copy($scope.calculatedField); + if(!$scope.result.aggregationSelected) $scope.result.aggregationSelected = 'NONE'; + $scope.result.funcSummary = $scope.result.aggregationSelected == 'NONE' ? 'SUM' : $scope.result.aggregationSelected; + $scope.result.aliasToShow = $scope.result.alias; + $scope.result.name = $scope.result.alias; + $scope.result.fieldType = 'MEASURE'; + $scope.result.isCalculated = true; + $scope.result.type = "java.lang.Double"; + promise.resolve($scope.result); + $mdDialog.hide(); + + },function(error){ + $scope.toastifyMsg('warning',$scope.translate.load(error)); return; - } - $scope.result = angular.copy($scope.calculatedField); - if(!$scope.result.aggregationSelected) $scope.result.aggregationSelected = 'NONE'; - $scope.result.funcSummary = $scope.result.aggregationSelected == 'NONE' ? 'SUM' : $scope.result.aggregationSelected; - $scope.result.aliasToShow = $scope.result.alias; - $scope.result.name = $scope.result.alias; - $scope.result.fieldType = 'MEASURE'; - $scope.result.isCalculated = true; - $scope.result.type = "java.lang.Double"; - promise.resolve($scope.result); - $mdDialog.hide(); - - },function(error){ - $scope.toastifyMsg('warning',error); - return; - }) - + }) + }else $scope.toastifyMsg('warning',$scope.translate.load("kn.cockpit.calculatedfield.validation.error.invalidalias")); } $scope.cancelConfiguration=function(){ $mdDialog.cancel(); @@ -289,7 +314,7 @@ along with this program. If not, see . $scope.resetFormula = function(){ $scope.calculatedField.formulaEditor = ''; - $scope.calculatedField.aggregationSelected = $scope.calculatedField.datasetOrTableFlag ? 'SUM' : 'NONE'; + $scope.calculatedField.aggregationSelected = 'NONE'; } $scope.isSolrDataset = function() { diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedFieldMode.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedFieldMode.js index 092d025f7e3..67d7e591096 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedFieldMode.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/directives/commons/calculated-field/calculatedFieldMode.js @@ -3,8 +3,20 @@ CodeMirror.defineSimpleMode("calculatedFieldMode", { regex: /(Sum|Locate|Min|Max|Count|Length|Avg|Concat|Substring)/, token: ["keyword"] },{ + // aggregations regex: /((?:AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)\()(\"[a-zA-Z0-9\-\_\s]*\")(\))/, token: ["keyword", "field", "keyword"] + },{ + // totals + regex: /((?:TOTAL_SUM|TOTAL_AVG|TOTAL_MIN|TOTAL_MAX|TOTAL_COUNT)\()(\"[a-zA-Z0-9\-\_\s]*\")(\))/, + token: ["keyword", "field", "keyword"] + },{ + regex: /((?:TOTAL_SUM|TOTAL_AVG|TOTAL_MIN|TOTAL_MAX|TOTAL_COUNT)\()([a-zA-Z0-9\-\+\/\*\_\s\$\{\}\"]*)(\))/, + token: ["keyword", "field", "keyword"] + },{ + // functions + regex: /((?:NULLIF)\()(\s?\"[a-zA-Z0-9\-\_\s]*\"|\$[a-zA-Z0-9\-\+\/\*\_\s\{\}\"]*)(\s?,\s?)([0-9]*\s?)(\))/, + token: ["keyword", "field", "separator","value" , "keyword"] },{ regex: /((?:AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT)\()([a-zA-Z0-9\-\+\/\*\_\s\$\{\}\"]*)(\))/, token: ["keyword", "", "keyword"] diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/factory/cockpitModule_generalOptions.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/factory/cockpitModule_generalOptions.js index 4ba89fa1fe4..7e6cc2a150d 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/factory/cockpitModule_generalOptions.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/factory/cockpitModule_generalOptions.js @@ -168,10 +168,10 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( conditions : ['>','<','==','>=','<=','!='], calculatedFieldsFunctions: [ { - "syntax":"SUM( Field )", + "syntax":"SUM( "+sbiModule_translate.load("kn.generic.field")+" )", "description":sbiModule_translate.load("kn.cockpit.functions.aggregation.sum"), - "body":"SUM(field)", - "name":"Sum", + "body":"SUM("+sbiModule_translate.load("kn.generic.field")+")", + "name":"SUM", "arguments":[ { "name":"Field", @@ -184,13 +184,13 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( } ], "output":"Number", - "type":"aggregation" + "type":sbiModule_translate.load("kn.cockpit.functions.type.aggregation") }, { - "syntax":"MIN( Field )", + "syntax":"MIN( "+sbiModule_translate.load("kn.generic.field")+" )", "description":sbiModule_translate.load("kn.cockpit.functions.aggregation.min"), - "body":"MIN(field)", - "name":"Min", + "body":"MIN("+sbiModule_translate.load("kn.generic.field")+")", + "name":"MIN", "arguments":[ { "name":"Field", @@ -203,13 +203,13 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( } ], "output":"Number", - "type":"aggregation" + "type":sbiModule_translate.load("kn.cockpit.functions.type.aggregation") }, { - "syntax":"MAX( Field )", + "syntax":"MAX( "+sbiModule_translate.load("kn.generic.field")+" )", "description":sbiModule_translate.load("kn.cockpit.functions.aggregation.max"), - "body":"MAX(field)", - "name":"Max", + "body":"MAX("+sbiModule_translate.load("kn.generic.field")+")", + "name":"MAX", "arguments":[ { "name":"Field", @@ -222,13 +222,13 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( } ], "output":"Number", - "type":"aggregation" + "type":sbiModule_translate.load("kn.cockpit.functions.type.aggregation") }, { - "syntax":"COUNT( Field )", + "syntax":"COUNT( "+sbiModule_translate.load("kn.generic.field")+" )", "description":sbiModule_translate.load("kn.cockpit.functions.aggregation.count"), - "body":"COUNT(field)", - "name":"Count", + "body":"COUNT("+sbiModule_translate.load("kn.generic.field")+")", + "name":"COUNT", "arguments":[ { "name":"Field", @@ -241,13 +241,13 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( } ], "output":"Integer", - "type":"aggregation" + "type":sbiModule_translate.load("kn.cockpit.functions.type.aggregation") }, { - "syntax":"AVG( Field )", + "syntax":"AVG( "+sbiModule_translate.load("kn.generic.field")+" )", "description":sbiModule_translate.load("kn.cockpit.functions.aggregation.avg"), - "body":"AVG(field)", - "name":"Average", + "body":"AVG("+sbiModule_translate.load("kn.generic.field")+")", + "name":"AVG", "arguments":[ { "name":"Field", @@ -260,8 +260,127 @@ angular.module('cockpitModule').factory('cockpitModule_generalOptions',function( } ], "output":"Number", - "type":"aggregation" - },/* + "type":sbiModule_translate.load("kn.cockpit.functions.type.aggregation") + }, + { + "syntax":"TOTAL_SUM( "+sbiModule_translate.load("kn.generic.field")+" )", + "description":sbiModule_translate.load("kn.cockpit.functions.total.sum"), + "body":"TOTAL_SUM("+sbiModule_translate.load("kn.generic.field")+")", + "name":"TOTAL_SUM", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.totals") + },{ + "syntax":"TOTAL_AVG( "+sbiModule_translate.load("kn.generic.field")+" )", + "description":sbiModule_translate.load("kn.cockpit.functions.total.avg"), + "body":"TOTAL_AVG("+sbiModule_translate.load("kn.generic.field")+")", + "name":"TOTAL_AVG", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.totals") + },{ + "syntax":"TOTAL_MIN( "+sbiModule_translate.load("kn.generic.field")+" )", + "description":sbiModule_translate.load("kn.cockpit.functions.total.min"), + "body":"TOTAL_MIN("+sbiModule_translate.load("kn.generic.field")+")", + "name":"TOTAL_MIN", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.totals") + },{ + "syntax":"TOTAL_MAX( "+sbiModule_translate.load("kn.generic.field")+" )", + "description":sbiModule_translate.load("kn.cockpit.functions.total.max"), + "body":"TOTAL_MAX("+sbiModule_translate.load("kn.generic.field")+")", + "name":"TOTAL_MAX", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.totals") + },{ + "syntax":"TOTAL_COUNT( "+sbiModule_translate.load("kn.generic.field")+" )", + "description":sbiModule_translate.load("kn.cockpit.functions.total.count"), + "body":"TOTAL_COUNT("+sbiModule_translate.load("kn.generic.field")+")", + "name":"TOTAL_COUNT", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.totals") + },{ + "syntax":"NULLIF( "+sbiModule_translate.load("kn.generic.field")+" , "+sbiModule_translate.load("kn.generic.expression")+")", + "description":sbiModule_translate.load("kn.cockpit.functions.nullif"), + "body":"NULLIF("+sbiModule_translate.load("kn.generic.field")+", 0)", + "name":"NULLIF", + "arguments":[ + { + "name":"Field", + "expected_value":"", + "default_value":"", + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + },{ + "name":"Expression", + "expected_value":"", + "default_value": 0, + "argument_description":sbiModule_translate.load("kn.cockpit.functions.argument.number"), + "hidden":false, + "type":null, + "placeholder":"" + } + ], + "output":"Number", + "type":sbiModule_translate.load("kn.cockpit.functions.type.functions") + } + + /* { "syntax":"Concat(expression1, expression2, expression3,...)", "description":"If expression is a numeric value, it will be converted to a binary string. \n\t\t\tIf all expressions are nonbinary strings, this function will return a nonbinary string. \n\t\t\tIf any of the expressions is a binary string, this function will return a binary string. \n\t\t\tIf any of the expressions is a NULL, this function will return a NULL value..", diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_backwardCompatibility.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_backwardCompatibility.js index 30eda819b2f..a92eca9f07f 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_backwardCompatibility.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_backwardCompatibility.js @@ -59,6 +59,9 @@ along with this program. If not, see . if(!self.compareVersion("6.3.0",template.knowageVersion)){ if(template.configuration && typeof(template.configuration.showScreenshot)=='undefined') template.configuration.showScreenshot = true; } + if(!self.compareVersion("7.3.0",template.knowageVersion)){ + if(template.configuration && typeof(template.configuration.showExcelExport)=='undefined') template.configuration.showExcelExport = true; + } //Cycle trough all widgets for(var sheet in template.sheets){ @@ -215,7 +218,7 @@ along with this program. If not, see . delete model.content.columnSelectedOfDataset; } } - + if(!self.compareVersion("7.3.0",version)){ if(model.type=='table' || model.type=='discovery'){ for(var k in model.content.columnSelectedOfDataset){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_customWidgetServices.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_customWidgetServices.js new file mode 100644 index 00000000000..39b6105feca --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_customWidgetServices.js @@ -0,0 +1,394 @@ +/* +Knowage, Open Source Business Intelligence suite +Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + +Knowage is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + +Knowage 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 Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + */ + +/** + * @authors Radmila Selakovic (radmila.selakovic@eng.it) + * + */ +angular.module("customWidgetAPI",[]).service("datastore",function($filter){ + + function datastore(data) { + this.data = data; + } + + + var globalTree = []; + function hierarchy(tree) { + this.tree = tree; + globalTree = tree; + } + + function node (node){ + for (var property in node) { + this[property] = node[property]; + } + + } + datastore.prototype.setData = function (data) { + this.data = transformDataStore(data); + } + + datastore.prototype.getRecords = function () { + return angular.copy(this.data.rows); + } + datastore.prototype.getDataArray = function (getDataArrayFn){ + var dataArray = []; + for(var i=0; i-1)parent = node; + } else { + for(var j = 0; j -1)parent = node[j]; + } + } + + + }) +//new node + return parent; + } + + node.prototype.getChildren = function () { + return this.children + } + + node.prototype.getSiblings = function () { + return this.getParent().children; + } + + var findElementIndex = function(array,element){ + for(var i =0;i-1 && columns[columnIndex].fieldType.toUpperCase()=="MEASURE"){ + var aggregationIndex = sbiModule_util.findInArray(aggregations.measures, 'columnName', p2); + if(aggregationIndex==-1){ + aggregations.measures.push({ + alias:columns[columnIndex].alias, + columnName:columns[columnIndex].name, + funct:columns[columnIndex].funcSummary, + id:columns[columnIndex].alias, + orderColumn:"", + orderType:"" + }) + } + } + //missing part for attributes + }) + } else { + this.addNewColumnToAggregations(obj[attrname], aggregations, columns); + } + } + } + // Returns Selections with Filters for Single Widget this.getWidgetSelectionsAndFilters = function(widgetObject, dataset, loadDomainValues) { var filtersToSend = {}; @@ -1105,7 +1144,6 @@ angular.module("cockpitModule").service("cockpitModule_datasetServices",function if(ngModel.type == "table"){ if(col.isCalculated) { - obj.datasetOrTableFlag = col.datasetOrTableFlag ? true : false; obj["formula"] = col.formula; }else obj["columnName"] = col.name; @@ -1566,8 +1604,8 @@ angular.module("cockpitModule").service("cockpitModule_datasetServices",function var columnsToshowIndex = []; var localModel = model; var datasetId = dataset.id.dsId; - model.dataset = {} - model.dataset.dsId = datasetId; + //model.dataset = {} + //model.dataset.dsId = datasetId; var regAggFunctions = 'AVG|MIN|MAX|SUM|COUNT_DISTINCT|COUNT|DISTINCT COUNT' diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_exportWidgetService.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_exportWidgetService.js index 97c322a8760..49ed691bee4 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_exportWidgetService.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_exportWidgetService.js @@ -18,9 +18,9 @@ (function(){ angular.module("cockpitModule") - .service("cockpitModule_exportWidgetService", ['$q', '$httpParamSerializer', '$mdToast', 'sbiModule_config', 'sbiModule_user', 'sbiModule_download', 'sbiModule_translate', 'sbiModule_restServices', 'sbiModule_messaging', 'sbiModule_cockpitDocument', 'cockpitModule_datasetServices', 'cockpitModule_widgetSelection', exportWidgetService]); + .service("cockpitModule_exportWidgetService", ['$q', '$httpParamSerializer', '$mdToast', 'sbiModule_config', 'sbiModule_user', 'sbiModule_download', 'sbiModule_translate', 'sbiModule_restServices', 'sbiModule_messaging', 'sbiModule_cockpitDocument', 'cockpitModule_datasetServices', 'cockpitModule_widgetSelection','cockpitModule_properties', exportWidgetService]); - function exportWidgetService ($q, $httpParamSerializer, $mdToast, sbiModule_config, sbiModule_user, sbiModule_download, sbiModule_translate, sbiModule_restServices, sbiModule_messaging, sbiModule_cockpitDocument, cockpitModule_datasetServices, cockpitModule_widgetSelection) { + function exportWidgetService ($q, $httpParamSerializer, $mdToast, sbiModule_config, sbiModule_user, sbiModule_download, sbiModule_translate, sbiModule_restServices, sbiModule_messaging, sbiModule_cockpitDocument, cockpitModule_datasetServices, cockpitModule_widgetSelection, cockpitModule_properties) { var objToReturn = {}; objToReturn.exportWidgetToExcel = function (type, widget, options) { @@ -69,10 +69,30 @@ requestUrl.exportWidget = exportWidget; } + if (!angular.equals(cockpitModule_properties.VARIABLES,{})) { + for (var k in widget.content.columnSelectedOfDataset) { + if(Array.isArray(widget.content.columnSelectedOfDataset[k].variables) && widget.content.columnSelectedOfDataset[k].variables.length) { + if (widget.type == "table" && widget.content.columnSelectedOfDataset[k].variables[0].action == 'header') { + for (var j in cockpitModule_properties.VARIABLES) { + if (j == widget.content.columnSelectedOfDataset[k].variables[0].variable){ + widget.content.columnSelectedOfDataset[k].aliasToShow = cockpitModule_properties.VARIABLES[j]; + } + } + } + + } + } + } + var dsId = widget.dataset.dsId; var dataset = cockpitModule_datasetServices.getDatasetById(dsId); - - var aggregation = cockpitModule_widgetSelection.getAggregation(widget, dataset); + var aggregation; + if (widget.settings) { + aggregation = cockpitModule_widgetSelection.getAggregation(widget, dataset, widget.settings.sortingColumn,widget.settings.sortingOrder); + } + else { + aggregation = cockpitModule_widgetSelection.getAggregation(widget, dataset) + } // cleanAggregation(widget, aggregation); var loadDomainValues = widget.type == "selector" ? true : false; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_generalServices.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_generalServices.js index de16f17e823..605efec3eec 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_generalServices.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_generalServices.js @@ -202,16 +202,14 @@ angular.module("cockpitModule").service("cockpitModule_generalServices",function //get templates location gs.getTemplateUrl = function(widget,template,format){ - var basePath = sbiModule_config.host; var templatesUrl = sbiModule_config.dynamicResourcesEnginePath + '/angular_1.4/cockpit/directives/cockpit-widget/widget/'+widget+'/templates/'; - return basePath + templatesUrl + template + (format || '.html'); - } + return window.location.origin + templatesUrl + template + (format || '.html'); + } //get tools location gs.getToolsUrl = function(){ - var basePath = sbiModule_config.host; return sbiModule_config.dynamicResourcesEnginePath + '/angular_1.4/cockpit/tools/commons/'; - } + } function saveCockpitController($scope, $mdDialog, sbiModule_translate, kn_regex){ $scope.translate = sbiModule_translate; diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_helperDescriptors.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_helperDescriptors.js index f1f0e08a4ab..d4c3dceb060 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_helperDescriptors.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_helperDescriptors.js @@ -24,7 +24,7 @@ angular.module('cockpitModule').service('cockpitModule_helperDescriptors',functi }return true; } - self.htmlHelperJSON = function(datasetId,meta,parameters,aggregations,cross,availableDatasets){ + self.htmlHelperJSON = function(datasetId,meta,parameters,aggregations,cross,availableDatasets,variables){ return [ { 'label':sbiModule_translate.load('kn.cockpit.html.tag1'), @@ -63,7 +63,7 @@ angular.module('cockpitModule').service('cockpitModule_helperDescriptors',functi 'label':sbiModule_translate.load('kn.cockpit.html.tag2'), 'name': 'parameter', 'description':sbiModule_translate.load('kn.cockpit.html.tag2.desc'), - 'hidden': self.isEmpty(cockpitModule_analyticalDrivers), + 'hidden': self.isEmpty(parameters), 'hiddenMessage': 'no parameter available', 'inputs': [ { 'name':'parameter', @@ -183,11 +183,24 @@ angular.module('cockpitModule').service('cockpitModule_helperDescriptors',functi 'type': 'select', 'options': !datasetId || meta, 'flex':'flex-100'}] + }, + { + 'label':sbiModule_translate.load('kn.cockpit.html.tag11'), + 'name': 'active-selection', + 'description': sbiModule_translate.load('kn.cockpit.html.tag11.desc'), + 'hidden': !variables ? true : false, + 'hiddenMessage': 'no variable present', + 'tag':"[kn-variable='%%variable%%']", + 'inputs': [ + { 'name':'variable', + 'type': 'select', + 'flex':'flex-100', + 'options': variables}] } ] } - self.pythonHelperJSON = function(datasetId,datasetLabel,meta,parameters,aggregations,cross,availableDatasets){ + self.pythonHelperJSON = function(datasetId,datasetLabel,meta,drivers,aggregations,cross,availableDatasets){ return [ { 'label':sbiModule_translate.load('kn.cockpit.python.tag1'), @@ -204,17 +217,48 @@ angular.module('cockpitModule').service('cockpitModule_helperDescriptors',functi 'tag': datasetLabel + "[\"%%column%%\"]"}, { 'label':sbiModule_translate.load('kn.cockpit.python.tag2'), - 'name': 'parameter', + 'name': 'driver', 'description':sbiModule_translate.load('kn.cockpit.python.tag2.desc'), 'hidden': self.isEmpty(cockpitModule_analyticalDrivers), - 'hiddenMessage': 'no parameter available', + 'hiddenMessage': 'no analytical driver available', 'inputs': [ - { 'name':'parameter', + { 'name':'driver', 'type': 'select', - 'options': parameters, + 'options': drivers, + 'flex':'flex-100'} + ], + 'tag':"$P{%%driver%%}"} + ] + } + + self.rHelperJSON = function(datasetId,datasetLabel,meta,drivers,aggregations,cross,availableDatasets){ + return [ + { + 'label':sbiModule_translate.load('kn.cockpit.R.tag1'), + 'name': 'column', + 'description': sbiModule_translate.load('kn.cockpit.R.tag1.desc'), + 'hidden': !datasetId ? true : false, + 'hiddenMessage': sbiModule_translate.load('kn.cockpit.R.nodataset'), + 'inputs': [ + { 'name':'column', + 'type': 'select', + 'options': !datasetId || meta, + 'flex':'flex-100'} + ], + 'tag': datasetLabel + "[\"%%column%%\"]"}, + { + 'label':sbiModule_translate.load('kn.cockpit.R.tag2'), + 'name': 'driver', + 'description':sbiModule_translate.load('kn.cockpit.R.tag2.desc'), + 'hidden': self.isEmpty(cockpitModule_analyticalDrivers), + 'hiddenMessage': 'no analytical driver available', + 'inputs': [ + { 'name':'driver', + 'type': 'select', + 'options': drivers, 'flex':'flex-100'} ], - 'tag':"$P{%%parameter%%}"} + 'tag':"$P{%%driver%%}"} ] } }); \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapServices.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapServices.js index 362dba51f44..a193d1cbdbb 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapServices.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapServices.js @@ -67,74 +67,78 @@ var lon; var lat; var isSimpleMarker = true; - for(var r=0; r < values.rows.length; r++){ - //get coordinates - var geometry; - var feature; - var row = values.rows[r]; - geoFieldValue = row[geoFieldName].trim(); - if (!geoFieldConfig.properties.coordType){ - //retrocompatibility management (just string type) - geoFieldConfig.properties.coordType = 'string'; - geoFieldConfig.properties.coordFormat = 'lon lat'; - } - if (geoFieldConfig.properties.coordType == 'json'){ + for(var r=0; r < values.rows.length; r++) { + try { + //get coordinates + var geometry; + var feature; + var row = values.rows[r]; + geoFieldValue = row[geoFieldName].trim(); + if (!geoFieldConfig.properties.coordType){ + //retrocompatibility management (just string type) + geoFieldConfig.properties.coordType = 'string'; + geoFieldConfig.properties.coordFormat = 'lon lat'; + } + if (geoFieldConfig.properties.coordType == 'json'){ - feature = new ol.format.GeoJSON().readFeatures(geoFieldValue, { - dataProjection: 'EPSG:4326', - featureProjection: 'EPSG:3857' - }); + feature = new ol.format.GeoJSON().readFeatures(geoFieldValue, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); - if (Array.isArray(feature)) { - for (var i in feature) { - var currFeature = feature[i]; + if (Array.isArray(feature)) { + for (var i in feature) { + var currFeature = feature[i]; - ms.setUpGeoJSONFeature(currFeature, config, row, configColumns, values); - ms.setUpSelectedMeasure(selectedMeasure, config, values); + ms.setUpGeoJSONFeature(currFeature, config, row, configColumns, values); + ms.setUpSelectedMeasure(selectedMeasure, config, values); - featuresSource.addFeature(currFeature); - } - } else { + featuresSource.addFeature(currFeature); + } + } else { - ms.setUpGeoJSONFeature(feature, config, row, configColumns, values); - ms.setUpSelectedMeasure(selectedMeasure, config, values); + ms.setUpGeoJSONFeature(feature, config, row, configColumns, values); + ms.setUpSelectedMeasure(selectedMeasure, config, values); - featuresSource.addFeature(feature); - } + featuresSource.addFeature(feature); + } - } else if (geoFieldConfig.properties.coordType == 'wkt') { + } else if (geoFieldConfig.properties.coordType == 'wkt') { - feature = new ol.format.WKT().readFeature(geoFieldValue, { - dataProjection: 'EPSG:4326', - featureProjection: 'EPSG:3857' - }); + feature = new ol.format.WKT().readFeature(geoFieldValue, { + dataProjection: 'EPSG:4326', + featureProjection: 'EPSG:3857' + }); - ms.setUpWKTFeature(feature, config, row, configColumns, values); - ms.setUpSelectedMeasure(selectedMeasure, config, values); + ms.setUpWKTFeature(feature, config, row, configColumns, values); + ms.setUpSelectedMeasure(selectedMeasure, config, values); - featuresSource.addFeature(feature); - } else if (geoFieldConfig.properties.coordType == 'string') { - if (geoFieldConfig.properties.coordType == 'string' && IsJsonString(geoFieldValue)){ - console.log("Location is set as STRING but its value has a JSON format. Please check the configuration: ["+geoFieldValue+"]"); - sbiModule_messaging.showInfoMessage(sbiModule_translate.load('sbi.cockpit.map.stringInvalid').replace("{0}",geoColumn).replace("{1}",geoFieldValue.substring(0,20)+'...'), 'Title', 0); - return null; - } - isSimpleMarker = true; - geometry = ms.getGeometry(geoColumn, geoFieldConfig, geoFieldValue); + featuresSource.addFeature(feature); + } else if (geoFieldConfig.properties.coordType == 'string') { + if (geoFieldConfig.properties.coordType == 'string' && IsJsonString(geoFieldValue)){ + console.log("Location is set as STRING but its value has a JSON format. Please check the configuration: ["+geoFieldValue+"]"); + sbiModule_messaging.showInfoMessage(sbiModule_translate.load('sbi.cockpit.map.stringInvalid').replace("{0}",geoColumn).replace("{1}",geoFieldValue.substring(0,20)+'...'), 'Title', 0); + return null; + } + isSimpleMarker = true; + geometry = ms.getGeometry(geoColumn, geoFieldConfig, geoFieldValue); - //set ol objects - feature = new ol.Feature(geometry); + //set ol objects + feature = new ol.Feature(geometry); - //at least add the layer owner - feature.set("parentLayer", config.layerID); - feature.set("isSimpleMarker", isSimpleMarker); - feature.set("sourceType", (config.markerConf && config.markerConf.type ) ? config.markerConf.type : "simple"); - ms.addDsPropertiesToFeature(feature, row, configColumns, values.metaData.fields); - ms.setUpSelectedMeasure(selectedMeasure, config, values); + //at least add the layer owner + feature.set("parentLayer", config.layerID); + feature.set("isSimpleMarker", isSimpleMarker); + feature.set("sourceType", (config.markerConf && config.markerConf.type ) ? config.markerConf.type : "simple"); + ms.addDsPropertiesToFeature(feature, row, configColumns, values.metaData.fields); + ms.setUpSelectedMeasure(selectedMeasure, config, values); - featuresSource.addFeature(feature); + featuresSource.addFeature(feature); + } + } catch(err) { + console.log("Error getting feature from row " + r + ". The original error was: " + err + ". Skipping to the next row..."); } } @@ -158,11 +162,11 @@ if (Array.isArray(value)) coord = value; else{ - if (value.indexOf(" ") > 0){ + if (value.indexOf(" ") > 0) { coord = value.split(" "); - }else if (value.indexOf(",")){ + } else if (value.indexOf(",")) { coord = value.split(","); - }else{ + } else{ sbiModule_messaging.showInfoMessage(sbiModule_translate.load('sbi.cockpit.map.lonLatError').replace("{0}",geocol).replace("{1}",value.substring(0,20)+'...'), 'Title', 0); console.log("Error getting longitude and latitude from column value ["+ geocol +"]. Check the dataset and its metadata."); return null; @@ -175,18 +179,16 @@ } //setting lon, lat values with correct order (LON, LAT) + var lat, lon; switch(config.properties.coordFormat) { - case "lon lat": - lon = (typeof coord[0] === 'string') ? parseFloat(coord[0].trim()) : coord[0]; - lat = (typeof coord[1] === 'string') ? parseFloat(coord[1].trim()) : coord[1]; - break; - case "lat lon": - lon = (typeof coord[1] === 'string') ? parseFloat(coord[1].trim()) : coord[1]; - lat = (typeof coord[0] === 'string') ? parseFloat(coord[0].trim()) : coord[0]; - break; - default: - lon = (typeof coord[0] === 'string') ? parseFloat(coord[0].trim()) : coord[0]; - lat = (typeof coord[1] === 'string') ? parseFloat(coord[1].trim()) : coord[1]; + case "lat lon": + lon = (typeof coord[1] === 'string') ? parseFloat(coord[1].trim()) : coord[1]; + lat = (typeof coord[0] === 'string') ? parseFloat(coord[0].trim()) : coord[0]; + break; + case "lon lat": + default: + lon = (typeof coord[0] === 'string') ? parseFloat(coord[0].trim()) : coord[0]; + lat = (typeof coord[1] === 'string') ? parseFloat(coord[1].trim()) : coord[1]; } return [lon, lat]; @@ -346,6 +348,16 @@ return array[index] / length; }); + } else if (geometry instanceof ol.geom.LineString) { + + var coordsMatrix = geometry.getCoordinates(); + var length = coordsMatrix.length; + + coord = coordsMatrix.reduce(toSum) + .map(function(element, index, array) { + return array[index] / length; + }); + } else if (geometry instanceof ol.geom.Polygon) { var coordsMatrix = geometry.getCoordinates(); @@ -372,31 +384,31 @@ console.log("Cannot determine the center of geomerty: " + geometry); } - } else { - //string && json - if (source.getFeatures()[0].getGeometry().getType().toUpperCase() == 'POINT') - coord = source.getFeatures()[0].getGeometry().getCoordinates(); + } else { + //string && json + if (source.getFeatures()[0].getGeometry().getType().toUpperCase() == 'POINT') + coord = source.getFeatures()[0].getGeometry().getCoordinates(); else if (source.getFeatures()[0].getGeometry().getType().toUpperCase() == 'MULTIPOLYGON') coord = source.getFeatures()[0].getGeometry().getCoordinates()[0][0][0]; else coord = source.getFeatures()[0].getGeometry().getCoordinates()[0][0]; - } - } - if(source.getFeatures().length>35){ - zoom = 4; + } + } + if(source.getFeatures().length>35){ + zoom = 4; }else{ zoom = 5; } - //update coordinates and zoom within the template - model.content.currentView.center = coord; - model.content.currentView.zoom = zoom; + //update coordinates and zoom within the template + model.content.currentView.center = coord; + model.content.currentView.zoom = zoom; - if (setValues){ - map.getView().setCenter(coord); - map.getView().setZoom(zoom); - } - } + if (setValues){ + map.getView().setCenter(coord); + map.getView().setZoom(zoom); + } + } } diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapThematizerServices.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapThematizerServices.js index 51936fb0650..0c69b8bada2 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapThematizerServices.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_mapThematizerServices.js @@ -60,13 +60,22 @@ } if (!localFeature.get('isSimpleMarker')){ - var userColor = (configMarker.style) ? configMarker.style.color : "grey"; + var fillColor = (configMarker.style && configMarker.style.color) ? configMarker.style.color : "grey"; + var borderColor = (configMarker.style && configMarker.style.borderColor) ? configMarker.style.borderColor : undefined; + if (props[mts.getActiveIndicator()] && props[mts.getActiveIndicator()].thresholdsConfig && props[mts.getActiveIndicator()].thresholdsConfig.length != 0) { - userColor = mts.getColorByThresholds(value, props); + fillColor = mts.getColorByThresholds(value, props) || fillColor; + } + + // To keep consistency with previous versions, in case of choropleth + // we don't use the border color + if (config.visualizationType == 'choropleth') { + borderColor = undefined; } - style = mts.getChoroplethStyles(value, parentLayer, userColor); + + style = mts.getChoroplethStyles(value, parentLayer, fillColor, borderColor); thematized = true; } @@ -203,14 +212,12 @@ }); } - mts.getChoroplethStyles=function(value, parentLayer, fixedColor){ - var color = mts.getChoroplethColor(value, parentLayer) || fixedColor; - var borderColor = "black"; + mts.getChoroplethStyles = function(value, parentLayer, fillColor, borderColor) { + var color = mts.getChoroplethColor(value, parentLayer) || fillColor; return [new ol.style.Style({ stroke: new ol.style.Stroke({ -// color: (borderColor) ? borderColor : color, - color: color, + color: borderColor || color, width: 2 }), fill: new ol.style.Fill({ @@ -230,20 +237,21 @@ // if (!color) color = (config.style && config.style.color) ? mts.rgbaToHex(config.style.color) : 'grey'; if (!alpha) alpha = (config.style && config.style.color) ? mts.rgbaToAlpha(config.style.color) : 1; + switch(config.type) { case "icon": //font-awesome var size = config.size || 100; style = new ol.style.Style({ - text: new ol.style.Text({ - text: config.icon.unicode, - font: '' + config.icon.fontWeight + ' ' + ((2*size) + '% ') + '"' + config.icon.fontFamily + '"', - fill: new ol.style.Fill({ - color: color, - opacity: alpha - }) - }) + text: new ol.style.Text({ + text: config.icon.unicode, + font: '' + config.icon.fontWeight + ' ' + ((2*size) + '% ') + '"' + config.icon.fontFamily + '"', + fill: new ol.style.Fill({ + color: color, + opacity: alpha + }) + }) }); break; @@ -259,15 +267,16 @@ }), scale: (config.scale) ? (config.scale/100) : 1, opacity: 1, - crossOrigin: null, - src: config[config.type] + crossOrigin: null, + src: config[config.type] })) - }); + }); break; default: - var defaultImg = new Image(12,12); - defaultImg.src = 'data:image/svg+xml,' + escape(' '); + var size = (config.size || 12); + var scale = size / 100; + var defaultImg = mts.getDefaultMarker(value, props, config); style = new ol.style.Style({ image: new ol.style.Icon( @@ -276,7 +285,8 @@ crossOrigin: 'anonymous', opacity: alpha, img: defaultImg, - imgSize: [12, 12] + imgSize: [100, 100], + scale: scale }) )}); break; @@ -285,9 +295,34 @@ return style; } + mts.defaultMarkerCache = {}; + + mts.clearDefaultMarkerCache = function() { + mts.defaultMarkerCache = {}; + } + + mts.getDefaultMarker = function(value, props, config) { + var color; + + if (props[mts.getActiveIndicator()] && props[mts.getActiveIndicator()].thresholdsConfig) color = mts.getColorByThresholds(value, props); + if (!color) color = (config.style && config.style.color) ? config.style.color : 'grey'; + + var layerName = props.parentLayer; + var key = "" + layerName + "|" + color; + + // A cache to maintaing styles for the marker + if (!(key in mts.defaultMarkerCache)) { + var defaultImg = new Image(); + defaultImg.src = 'data:image/svg+xml,' + encodeURIComponent(''); + mts.defaultMarkerCache[key] = defaultImg; + } + + return mts.defaultMarkerCache[key]; + } + mts.getColorByThresholds = function(value, props){ var config = props[mts.getActiveIndicator()].thresholdsConfig; - var toReturn = null; + var toReturn = undefined; var isEqualOp = false; for (c in config){ diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_variableService.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_variableService.js index a4e99a27160..137b0435940 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_variableService.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_variableService.js @@ -48,7 +48,7 @@ along with this program. If not, see . this.getVariableValue = function(variable){ return $q(function(resolve, reject) { if(variable.type == 'static') resolve( variable.value ); - if(variable.type == 'driver') resolve( cockpitModule_analyticalDrivers[variable.driver] ); + if(variable.type == 'driver') resolve( self.parseOldStyleDriver(cockpitModule_analyticalDrivers[variable.driver]) ); if(variable.type == 'profile') resolve( sbiModule_user.profileAttributes[variable.attribute] ); if(variable.type == 'dataset') { var tempDataset = cockpitModule_datasetServices.getDatasetById(variable.dataset); @@ -71,6 +71,14 @@ along with this program. If not, see . } }) } + + this.parseOldStyleDriver = function(oldDriver){ + var newDriver = oldDriver.replace(/\{([\;\,\_\s\-]{1})\{([^\}]*)\}([A-Z]*)\}/g,function(match, divider, params, type){ + newDriver = params.split(divider); + return newDriver.join(","); + }) + return newDriver; + } this.getVariablePlaceholders = function(textToParse){ var tempText = angular.copy(textToParse); diff --git a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_widgetSelection.js b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_widgetSelection.js index 74858c060f2..a6fdf4ca8e7 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_widgetSelection.js +++ b/knowagecockpitengine/src/main/webapp/js/src/angular_1.4/cockpit/services/cockpitModule_widgetSelection.js @@ -34,10 +34,28 @@ angular.module("cockpitModule").service("cockpitModule_widgetSelection",function this.getAggregation = function(ngModel,dataset,columnOrdering, reverseOrdering){ var measures = []; var categories = []; - var ds = dataset.label; + var ds = dataset && dataset.label; // var columns = ngModel==undefined ? undefined : ngModel.content.columnSelectedOfDataset; var columns = (ngModel==undefined || !ngModel.content.columnSelectedOfDataset) ? undefined :(Array.isArray(ngModel.content.columnSelectedOfDataset) ) ? ngModel.content.columnSelectedOfDataset : ngModel.content.columnSelectedOfDataset[dataset.id.dsId] ; + + if (ngModel && ngModel.type == "map") { + var dsId = dataset.id.dsId; + var allLayers = ngModel.content.layers; + for (var layerIdx in allLayers) { + var currLayer = allLayers[layerIdx]; + if (currLayer.dsId == dsId) { + columns = currLayer.content + .columnSelectedOfDataset + .filter(function(el) { + var type = el.fieldType; + return !(type == "ATTRIBUTE" && !el.properties.aggregateBy); + }); + break; + } + } + } + if(columns != undefined){ //create aggregation for(var i=0;i 0) { + for (var y in columnsNameArray) { + tempColumns.push(columnsMap[columnsNameArray[y]]); // pushes values not present into model + + } + } + + return tempColumns; + } + this.getAllWidgets=function(){ var ret = []; var numSheets = cockpitModule_template.sheets.length; @@ -190,7 +223,8 @@ angular.module("cockpitModule").service("cockpitModule_widgetServices",function( } } } - dsId = dataset.id.dsId; + if(dataset) dsId = dataset.id.dsId; + else dsId = ngModel.dataset.dsId[0]; //if it's a realtime dataset don't use backend filter on charts if (dataset && dataset.isRealtime && ngModel.content && ngModel.content.filters) { @@ -200,7 +234,7 @@ angular.module("cockpitModule").service("cockpitModule_widgetServices",function( // return cockpitModule_datasetServices.loadDatasetRecordsById(ngModel.dataset.dsId,page,itemPerPage,columnOrdering, reverseOrdering, ngModelCopy); return cockpitModule_datasetServices.loadDatasetRecordsById(dsId,page,itemPerPage,columnOrdering, reverseOrdering, ngModelCopy, nature); } - return cockpitModule_datasetServices.loadDatasetRecordsById(ngModel.dataset.dsId,page,itemPerPage,columnOrdering, reverseOrdering, ngModel, loadDomainValues, nature); + return cockpitModule_datasetServices.loadDatasetRecordsById(dsId,page,itemPerPage,columnOrdering, reverseOrdering, ngModel, loadDomainValues, nature); } return null; } @@ -280,31 +314,31 @@ angular.module("cockpitModule").service("cockpitModule_widgetServices",function( }; this.refreshWidget = function(element, config, nature, options, data, changedChartType){ - var currentSheet = -1; - if(nature != 'init'){ - for(i in cockpitModule_template.sheets){ - for(j in cockpitModule_template.sheets[i].widgets){ - if(cockpitModule_template.sheets[i].widgets[j].id == config.id){ - currentSheet = cockpitModule_template.sheets[i].index; - break; - } - } - } - } + var currentSheet = -1; + if(nature != 'init'){ + for(i in cockpitModule_template.sheets){ + for(j in cockpitModule_template.sheets[i].widgets){ + if(cockpitModule_template.sheets[i].widgets[j].id == config.id){ + currentSheet = cockpitModule_template.sheets[i].index; + break; + } + } + } + } - var dirtyIndex = cockpitModule_properties.DIRTY_WIDGETS.indexOf(config.id); - if(nature == 'init' || currentSheet == cockpitModule_properties.CURRENT_SHEET){ - if(dirtyIndex > -1){ - cockpitModule_properties.DIRTY_WIDGETS.splice(dirtyIndex, 1); - } + var dirtyIndex = cockpitModule_properties.DIRTY_WIDGETS.indexOf(config.id); + if(nature == 'init' || currentSheet == cockpitModule_properties.CURRENT_SHEET){ + if(dirtyIndex > -1){ + cockpitModule_properties.DIRTY_WIDGETS.splice(dirtyIndex, 1); + } - var width = angular.element(element)[0].parentElement.offsetWidth; - var height = angular.element(element)[0].parentElement.offsetHeight; - if(data == undefined) { - if(nature == "fullExpand"){ + var width = angular.element(element)[0].parentElement.offsetWidth; + var height = angular.element(element)[0].parentElement.offsetHeight; + if(data == undefined) { + if(nature == "fullExpand"){ $rootScope.$broadcast("WIDGET_EVENT"+config.id,"REFRESH",{element:element,width:width,height:height,data:null,nature:nature,options:options}); - }else{ - if (config && config.dataset && config.dataset.dsId){ + }else{ + if (config && config.dataset && config.dataset.dsId){ // var dataset = cockpitModule_datasetServices.getDatasetById(config.dataset.dsId); var dataset; @@ -320,9 +354,9 @@ angular.module("cockpitModule").service("cockpitModule_widgetServices",function( } } - //for realtime dataset the associative selections are managed client side + //for realtime dataset the associative selections are managed client side if (dataset && dataset.isRealtime && dataset.useCache && (nature=='selections' || nature=='filters')){ - var selections = cockpitModule_widgetSelection.getCurrentSelections(dataset.label); + var selections = cockpitModule_widgetSelection.getCurrentSelections(dataset.label); var filters = cockpitModule_widgetSelection.getCurrentFilters(dataset.label); for (var filterProp in filters) { @@ -339,11 +373,11 @@ angular.module("cockpitModule").service("cockpitModule_widgetServices",function( } } - if (Object.keys(selections).length === 0 && selections.constructor === Object){ - //cleaned selections - this.realtimeSelections.length = 0; - } else { - //save dataset and selections inside this array (that can be watched outside) + if (Object.keys(selections).length === 0 && selections.constructor === Object){ + //cleaned selections + this.realtimeSelections.length = 0; + } else { + //save dataset and selections inside this array (that can be watched outside) var realtimeSelection = {'datasetId':config.dataset.dsId, 'selections':selections}; var found = false; for(var i=0; i. + */ + +/** + * @authors Radmila Selakovic (radmila.selakovic@eng.it) + * + */ +angular.module("cockpitModule").service("datastoreService",function(){ + + this.datastore1 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"QUARTER","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"STORE_ID","dataIndex":"column_2","type":"float","multiValue":false},{"name":"column_3","header":"THE_DATE","dataIndex":"column_3","type":"date","subtype":"timestamp","dateFormat":"d/m/Y H:i:s.uuu","dateFormatJava":"dd/MM/yyyy HH:mm:ss.SSS","multiValue":false},{"name":"column_4","header":"AMOUNT","dataIndex":"column_4","type":"float","multiValue":false}],"cacheDate":"2019-03-12 13:36:35.949"},"results":24,"rows":[{"id":1,"column_1":"Q1","column_2":"24","column_3":"01/01/1997 00:00:00.000","column_4":"210"},{"id":2,"column_1":"Q1","column_2":"24","column_3":"01/02/1997 00:00:00.000","column_4":"210"},{"id":3,"column_1":"Q1","column_2":"24","column_3":"01/03/1997 00:00:00.000","column_4":"210"},{"id":4,"column_1":"Q1","column_2":"24","column_3":"01/01/1998 00:00:00.000","column_4":"550"},{"id":5,"column_1":"Q1","column_2":"24","column_3":"01/02/1998 00:00:00.000","column_4":"550"},{"id":6,"column_1":"Q1","column_2":"24","column_3":"01/03/1998 00:00:00.000","column_4":"550"},{"id":7,"column_1":"Q2","column_2":"24","column_3":"01/04/1997 00:00:00.000","column_4":"210"},{"id":8,"column_1":"Q2","column_2":"24","column_3":"01/05/1997 00:00:00.000","column_4":"210"},{"id":9,"column_1":"Q2","column_2":"24","column_3":"01/06/1997 00:00:00.000","column_4":"210"},{"id":10,"column_1":"Q2","column_2":"24","column_3":"01/04/1998 00:00:00.000","column_4":"550"}]}; + + this.datastore2 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"QUARTER","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"THE_DATE","dataIndex":"column_2","type":"date","subtype":"timestamp","dateFormat":"d/m/Y H:i:s.uuu","dateFormatJava":"dd/MM/yyyy HH:mm:ss.SSS","multiValue":false},{"name":"column_3","header":"STORE_ID","dataIndex":"column_3","type":"float","multiValue":false},{"name":"column_4","header":"PRODUCT_FAMILY","dataIndex":"column_4","type":"string","multiValue":false},{"name":"column_5","header":"UNIT_SALES","dataIndex":"column_5","type":"float","multiValue":false},{"name":"column_6","header":"STORE_COST","dataIndex":"column_6","type":"float","multiValue":false}],"cacheDate":"2020-03-05 10:33:36.213"},"results":3928,"rows":[{"id":1,"column_1":"Q1","column_2":"28/01/1998 00:00:00.000","column_3":"1","column_4":"Drink","column_5":"48","column_6":"38.0323"},{"id":2,"column_1":"Q2","column_2":"19/04/1998 00:00:00.000","column_3":"1","column_4":"Drink","column_5":"44","column_6":"36.6181"},{"id":3,"column_1":"Q1","column_2":"27/03/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"75","column_6":"70.7084"},{"id":4,"column_1":"Q2","column_2":"18/04/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"112","column_6":"86.7598"},{"id":5,"column_1":"Q4","column_2":"24/11/1998 00:00:00.000","column_3":"1","column_4":"Food","column_5":"303","column_6":"274.2339"},{"id":6,"column_1":"Q4","column_2":"14/11/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"80","column_6":"65.998"},{"id":7,"column_1":"Q3","column_2":"25/08/1998 00:00:00.000","column_3":"2","column_4":"Food","column_5":"36","column_6":"31.5318"},{"id":8,"column_1":"Q1","column_2":"02/03/1998 00:00:00.000","column_3":"3","column_4":"Drink","column_5":"49","column_6":"37.6628"},{"id":9,"column_1":"Q2","column_2":"05/06/1998 00:00:00.000","column_3":"3","column_4":"Drink","column_5":"31","column_6":"27.965"},{"id":10,"column_1":"Q3","column_2":"13/07/1998 00:00:00.000","column_3":"3","column_4":"Food","column_5":"220","column_6":"189.1403"}]}; + + this.datastore3 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"QUARTER","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"UNITS_ORDERED_SUM","dataIndex":"column_2","type":"float","multiValue":false}],"cacheDate":"2020-03-05 10:33:36.265"},"results":4,"rows":[{"id":1,"column_1":"Q3","column_2":"1701490"},{"id":2,"column_1":"Q2","column_2":"1357292"},{"id":3,"column_1":"Q1","column_2":"1426572"},{"id":4,"column_1":"Q4","column_2":"1343842"}]}; + + this.datastore4 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"country","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"total_children","dataIndex":"column_2","type":"float","multiValue":false}],"cacheDate":"2020-03-05 16:28:45.713"},"results":3,"rows":[{"id":1,"column_1":"Canada","column_2":"20"},{"id":2,"column_1":"Mexico","column_2":"14"},{"id":3,"column_1":"USA","column_2":"82"}]}; + + this.datastore5 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"country","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"city","dataIndex":"column_2","type":"string","multiValue":false},{"name":"column_3","header":"total_children","dataIndex":"column_3","type":"float","multiValue":false}],"cacheDate":"2020-03-06 13:12:59.493"},"results":38,"rows":[{"id":1,"column_1":"Canada","column_2":"Burnaby","column_3":"4"},{"id":2,"column_1":"Canada","column_2":"Haney","column_3":"3"},{"id":3,"column_1":"Canada","column_2":"Ladner","column_3":"2"},{"id":4,"column_1":"Canada","column_2":"Oak Bay","column_3":"5"},{"id":5,"column_1":"Canada","column_2":"Richmond","column_3":"5"},{"id":6,"column_1":"Canada","column_2":"Sooke","column_3":"1"},{"id":7,"column_1":"Mexico","column_2":"Camacho","column_3":"2"},{"id":8,"column_1":"Mexico","column_2":"Merida","column_3":"5"},{"id":9,"column_1":"Mexico","column_2":"Mexico City","column_3":"4"},{"id":10,"column_1":"Mexico","column_2":"San Andres","column_3":"5"}]}; + + this.datastore6 = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"city","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"total_children","dataIndex":"column_2","type":"float","multiValue":false},{"name":"column_3","header":"num_children_at_home","dataIndex":"column_3","type":"float","multiValue":false}],"cacheDate":"2020-03-06 14:48:21.677"},"results":38,"rows":[{"id":1,"column_1":"Altadena","column_2":"7","column_3":"2"},{"id":2,"column_1":"Anacortes","column_2":"1","column_3":"1"},{"id":3,"column_1":"Arcadia","column_2":"8","column_3":"0"},{"id":4,"column_1":"Bellflower","column_2":"1","column_3":"0"},{"id":5,"column_1":"Bellingham","column_2":"4","column_3":"4"},{"id":6,"column_1":"Burbank","column_2":"2","column_3":"0"},{"id":7,"column_1":"Burnaby","column_2":"4","column_3":"4"},{"id":8,"column_1":"Camacho","column_2":"2","column_3":"2"},{"id":9,"column_1":"Chula Vista","column_2":"1","column_3":"0"},{"id":10,"column_1":"Concord","column_2":"4","column_3":"3"},{"id":11,"column_1":"Everett","column_2":"1","column_3":"0"},{"id":12,"column_1":"Haney","column_2":"3","column_3":"0"},{"id":13,"column_1":"Issaquah","column_2":"1","column_3":"1"},{"id":14,"column_1":"La Jolla","column_2":"2","column_3":"0"},{"id":15,"column_1":"La Mesa","column_2":"7","column_3":"1"},{"id":16,"column_1":"Ladner","column_2":"2","column_3":"0"},{"id":17,"column_1":"Lake Oswego","column_2":"4","column_3":"0"},{"id":18,"column_1":"Lebanon","column_2":"4","column_3":"2"},{"id":19,"column_1":"Lincoln Acres","column_2":"2","column_3":"2"},{"id":20,"column_1":"Lynnwood","column_2":"3","column_3":"0"},{"id":21,"column_1":"Merida","column_2":"5","column_3":"1"},{"id":22,"column_1":"Mexico City","column_2":"4","column_3":"0"},{"id":23,"column_1":"Mill Valley","column_2":"1","column_3":"1"},{"id":24,"column_1":"Milwaukie","column_2":"4","column_3":"0"},{"id":25,"column_1":"Novato","column_2":"3","column_3":"0"},{"id":26,"column_1":"Oak Bay","column_2":"5","column_3":"0"},{"id":27,"column_1":"Oakland","column_2":"1","column_3":"0"},{"id":28,"column_1":"Oregon City","column_2":"1","column_3":"0"},{"id":29,"column_1":"Renton","column_2":"6","column_3":"0"},{"id":30,"column_1":"Richmond","column_2":"5","column_3":"3"},{"id":31,"column_1":"San Andres","column_2":"5","column_3":"5"},{"id":32,"column_1":"Santa Cruz","column_2":"3","column_3":"2"},{"id":33,"column_1":"Santa Fe","column_2":"0","column_3":"0"},{"id":34,"column_1":"Seattle","column_2":"0","column_3":"0"},{"id":35,"column_1":"Sooke","column_2":"1","column_3":"0"},{"id":36,"column_1":"Spring Valley","column_2":"2","column_3":"0"},{"id":37,"column_1":"Tlaxiaco","column_2":"6","column_3":"3"},{"id":38,"column_1":"W. Linn","column_2":"1","column_3":"0"}]}; + + this.datastoreHierarchy = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"country","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"city","dataIndex":"column_2","type":"string","multiValue":false},{"name":"column_3","header":"total_children_SUM","dataIndex":"column_3","type":"float","multiValue":false}],"cacheDate":"2020-03-20 10:46:21.221"},"results":41,"rows":[{"id":1,"column_1":"Canada","column_2":"Burnaby","column_3":"4"},{"id":2,"column_1":"Canada","column_2":"Haney","column_3":"3"},{"id":3,"column_1":"Canada","column_2":"Ladner","column_3":"2"},{"id":4,"column_1":"Canada","column_2":"Oak Bay","column_3":"5"},{"id":5,"column_1":"Canada","column_2":"Richmond","column_3":"5"},{"id":6,"column_1":"Canada","column_2":"Sooke","column_3":"1"},{"id":7,"column_1":"Mexico","column_2":"Camacho","column_3":"0"},{"id":8,"column_1":"Mexico","column_2":"Merida","column_3":"5"},{"id":9,"column_1":"Mexico","column_2":"Mexico City","column_3":"4"},{"id":10,"column_1":"Mexico","column_2":"San Andres","column_3":"3"},{"id":11,"column_1":"Mexico","column_2":"Santa Fe","column_3":"0"},{"id":12,"column_1":"Mexico","column_2":"Tlaxiaco","column_3":"2"},{"id":13,"column_1":"USA","column_2":"Altadena","column_3":"7"},{"id":14,"column_1":"USA","column_2":"Anacortes","column_3":"1"},{"id":15,"column_1":"USA","column_2":"Arcadia","column_3":"8"},{"id":16,"column_1":"USA","column_2":"Bellflower","column_3":"1"},{"id":17,"column_1":"USA","column_2":"Bellingham","column_3":"4"},{"id":18,"column_1":"USA","column_2":"Burbank","column_3":"2"},{"id":19,"column_1":"USA","column_2":"Camacho","column_3":"2"},{"id":20,"column_1":"USA","column_2":"Chula Vista","column_3":"1"},{"id":21,"column_1":"USA","column_2":"Concord","column_3":"4"},{"id":22,"column_1":"USA","column_2":"Everett","column_3":"1"},{"id":23,"column_1":"USA","column_2":"Issaquah","column_3":"1"},{"id":24,"column_1":"USA","column_2":"La Jolla","column_3":"2"},{"id":25,"column_1":"USA","column_2":"La Mesa","column_3":"7"},{"id":26,"column_1":"USA","column_2":"Lake Oswego","column_3":"4"},{"id":27,"column_1":"USA","column_2":"Lebanon","column_3":"4"},{"id":28,"column_1":"USA","column_2":"Lincoln Acres","column_3":"2"},{"id":29,"column_1":"USA","column_2":"Lynnwood","column_3":"3"},{"id":30,"column_1":"USA","column_2":"Mill Valley","column_3":"1"},{"id":31,"column_1":"USA","column_2":"Milwaukie","column_3":"4"},{"id":32,"column_1":"USA","column_2":"Novato","column_3":"3"},{"id":33,"column_1":"USA","column_2":"Oakland","column_3":"1"},{"id":34,"column_1":"USA","column_2":"Oregon City","column_3":"1"},{"id":35,"column_1":"USA","column_2":"Renton","column_3":"6"},{"id":36,"column_1":"USA","column_2":"San Andres","column_3":"2"},{"id":37,"column_1":"USA","column_2":"Santa Cruz","column_3":"3"},{"id":38,"column_1":"USA","column_2":"Seattle","column_3":"0"},{"id":39,"column_1":"USA","column_2":"Spring Valley","column_3":"2"},{"id":40,"column_1":"USA","column_2":"Tlaxiaco","column_3":"4"},{"id":41,"column_1":"USA","column_2":"W. Linn","column_3":"1"}]}; +}); + diff --git a/knowagecockpitengine/src/main/webapp/js/src/messages/messages.properties b/knowagecockpitengine/src/main/webapp/js/src/messages/messages.properties index 14f2aaa5ea0..b8ed4fe555b 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/messages/messages.properties +++ b/knowagecockpitengine/src/main/webapp/js/src/messages/messages.properties @@ -46,7 +46,7 @@ sbi.chartengine.axisstylepopup.labelParams.rotationOfLabelYAxis=Rotation sbi.chartengine.axisstylepopup.labelParams.title=Labels sbi.chartengine.axisstylepopup.mainTickParams.tickColor=Tick color sbi.chartengine.axisstylepopup.mainTickParams.tickLength=Tick length (px) -sbi.chartengine.axisstylepopup.mainTickParams.tickPixelInterval=Tick pixel interval (px) +sbi.chartengine.axisstylepopup.mainTickParams.tickPixelInterval=Tick pixel interval sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.inside=Inside sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.outside=Outside sbi.chartengine.axisstylepopup.mainTickParams.tickPosition=Tick position @@ -56,7 +56,7 @@ sbi.chartengine.axisstylepopup.majorgrid=Major grid sbi.chartengine.axisstylepopup.majorminorgrid.color=Line color sbi.chartengine.axisstylepopup.minorgrid=Minor grid sbi.chartengine.axisstylepopup.minorTickParams.enable.minorTickInterval = Enable minor tick interval -sbi.chartengine.axisstylepopup.minorTickParams.minorTickInterval=Minor tick interval (px) +sbi.chartengine.axisstylepopup.minorTickParams.minorTickInterval=Minor tick interval sbi.chartengine.axisstylepopup.minorTickParams.minorTickLength=Minor tick length (px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickPosition=Minor tick position sbi.chartengine.axisstylepopup.minorTickParams.minorTickWidth=Minor tick width (px) @@ -199,6 +199,7 @@ sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMaxWidth=Maximum w sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMinHeight=Minimum height sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMinWidth=Minimum width sbi.chartengine.configuration.parallel.tooltip.parallelTooltipPadding=Text padding +sbi.chartengine.configuration.parallel.tooltip.maxNumberOfRecords = Maximum number of records to show tooltip sbi.chartengine.configuration.parallel.tooltip.title=Tooltip configuration sbi.chartengine.configuration.parallelAxesLinesAxisColNamePadd.emptyText=Insert axis column name padding sbi.chartengine.configuration.parallelAxesLinesBrushWidth.emptyText=Insert brush width @@ -720,6 +721,7 @@ sbi.cockpit.cross.outputParameter.column = Column sbi.cockpit.cross.outputParameter.dataset = Dataset sbi.cockpit.cross.outputParameter.dynamicvalue = Dynamic Value sbi.cockpit.cross.outputParameter.measurescolumnname = Measures column name +sbi.cockpit.cross.outputParameter.selectedcolumnname = Selected Column Name sbi.cockpit.cross.outputParameter.type = Type sbi.cockpit.cross.outputParameter.value = Value sbi.cockpit.cross.outputParameters = Output parameters list @@ -800,6 +802,7 @@ sbi.cockpit.editor.newwidget.description.html = Custom HTML code editor with sho sbi.cockpit.editor.newwidget.description.map = Interactive map with multiple layers representation. sbi.cockpit.editor.newwidget.description.selector = Selector widget to easily filter categories. sbi.cockpit.editor.newwidget.description.python = Write your own python code and create your visualization. +sbi.cockpit.editor.newwidget.description.R = Write your own R script and create your custom visualization. sbi.cockpit.editor.newwidget.description.discovery = Advanced faceted table to interact with Solr datasets. sbi.cockpit.editor.newwidget.info=Click on a widget to add it in the current cockpit sheet. sbi.cockpit.editor.newwidget.title=Select New Widget @@ -949,9 +952,11 @@ sbi.cockpit.map.lonLatError=Error getting longitude and latitude from column [ { sbi.cockpit.map.stringInvalid=Error getting coordinates from column [ {0} ] with value [ {1} ]. The content should be a STRING instead of JSON. Please check the configuration. sbi.cockpit.map.typeLayerNotManaged=Layer of type [ {0} ] not managed! sbi.cockpit.map.togglemapoptions = Toggle Map Options -sbi.cockpit.map.backgroundLayers=Background layers +sbi.cockpit.map.genericConfiguration=Map configuration sbi.cockpit.map.enableBaseLayer=Enable base layer sbi.cockpit.map.selectBackgroundLayer=Select background layer +sbi.cockpit.map.zoomFactor=Zoom factor +sbi.cockpit.map.showScale=Show scale sbi.cockpit.map.edit.layerColType=Type sbi.cockpit.map.edit.layerColName=Name sbi.cockpit.map.edit.layerColLabel=Label @@ -971,9 +976,37 @@ sbi.cockpit.map.edit.metadata.showOnDetail=Show on detail sbi.cockpit.map.edit.metadata.showOnMap=Show on map sbi.cockpit.map.edit.metadata.showOnFilter=Show on filter sbi.cockpit.map.edit.metadata.modalColumn=Modal column +sbi.cockpit.map.edit.metadata.aggregateBy=Aggregate by sbi.cockpit.map.edit.metadata.threshold=Threshold +sbi.cockpit.map.edit.metadata.style=Style sbi.cockpit.map.edit.metadata.delete=Delete sbi.cockpit.map.edit.metadata.upate=Update +sbi.cockpit.map.edit.visualization.cardName=Visualization types +sbi.cockpit.map.edit.visualization.common.preview=Preview +sbi.cockpit.map.edit.visualization.header.clusters=Clusters +sbi.cockpit.map.edit.visualization.header.choroplet=Analysis +sbi.cockpit.map.edit.visualization.header.marker=Markers +sbi.cockpit.map.edit.visualization.header.heatmap=Heatmap settings +sbi.cockpit.map.edit.visualization.cluster.radius=Radius Size +sbi.cockpit.map.edit.visualization.cluster.fontSize=Font size +sbi.cockpit.map.edit.visualization.cluster.fontColor=Font color +sbi.cockpit.map.edit.visualization.cluster.backgroundColor=Background color +sbi.cockpit.map.edit.visualization.choroplet.classes=Classes method +sbi.cockpit.map.edit.visualization.choroplet.classesByEqualIntervals=Classify by equal intervals +sbi.cockpit.map.edit.visualization.choroplet.classesByQuantils=Classify by quantils +sbi.cockpit.map.edit.visualization.choroplet.classesNumber=Classes number +sbi.cockpit.map.edit.visualization.choroplet.fromColor=From color +sbi.cockpit.map.edit.visualization.choroplet.toColor=To color +sbi.cockpit.map.edit.visualization.marker.defaultMarker=Default marker +sbi.cockpit.map.edit.visualization.marker.iconMarker=Icon marker +sbi.cockpit.map.edit.visualization.marker.imageMarker=Image Marker +sbi.cockpit.map.edit.visualization.marker.markerFromUrl=Image from web marker +sbi.cockpit.map.edit.visualization.marker.fillColor=Color +sbi.cockpit.map.edit.visualization.marker.borderColor=Border color +sbi.cockpit.map.edit.visualization.marker.scale=Scale (%) +sbi.cockpit.map.edit.visualization.marker.size=Size (%) +sbi.cockpit.map.edit.visualization.heatmap.radius=Radius +sbi.cockpit.map.edit.visualization.heatmap.blur=Blur sbi.cockpit.msg.deletetab.msg = Confirm current item delete? sbi.cockpit.msg.deletetab.title = Please confirm sbi.cockpit.msg.deletetaball.msg = Confirm all items delete? @@ -1255,6 +1288,7 @@ sbi.cockpit.table.missingdataset = Please Select a dataset sbi.cockpit.table.multiline = Allow Multiline sbi.cockpit.table.multiselectioncolor = Selection highlight Color sbi.cockpit.table.nocolumns = No Columns selected. +sbi.cockpit.table.nodefault = No default value set. sbi.cockpit.table.nomeasure = No measure to display. sbi.cockpit.table.nothreshold = No ranges declared sbi.cockpit.table.pinned = Pinned @@ -1290,6 +1324,9 @@ sbi.cockpit.widget.pivot = CrossTab sbi.cockpit.widget.python.environment = Environment sbi.cockpit.widget.python.library = Library sbi.cockpit.widget.python.version = Version +sbi.cockpit.widget.R.environment = Environment +sbi.cockpit.widget.R.library = Library +sbi.cockpit.widget.R.version = Version sbi.cockpit.widget.selection = Selection sbi.cockpit.widget.selection.message = Message sbi.cockpit.widget.selection.messagehint = If left empty the default message will be: "No active selections" @@ -1317,6 +1354,7 @@ sbi.cockpit.widget.table.rows = Rows sbi.cockpit.widget.table.summary = Summary sbi.cockpit.widget.table.summary.add = Add sbi.cockpit.widget.table.summary.addtooltip = Add Summary Row +sbi.cockpit.widget.table.summary.noPinnedColumnsWarning = Warning: no pinned column defined. No label will be shown. sbi.cockpit.widget.text = Text sbi.cockpit.widget.text.editor = Text Editor sbi.cockpit.widget.text.missingtext = Text is empty! @@ -1483,6 +1521,8 @@ sbi.cockpit.widgets.table.column.hideall = Hide All Columns sbi.cockpit.widgets.table.column.type = Type sbi.cockpit.widgets.table.column.aggregation = Aggregation sbi.cockpit.widgets.table.column.showall = Show All Columns +sbi.cockpit.widgets.table.column.summaryAggregation= Summary row Aggregation +sbi.cockpit.widgets.table.column.summaryDefaultAggregation = Columns Default Aggregation sbi.cockpit.widgets.table.column.summaryfunction = Summary Function sbi.cockpit.widgets.table.confirm.delete= Delete confirmation sbi.cockpit.widgets.table.confirm.delete.text= Are you sure you want to delete all columns? @@ -1782,8 +1822,13 @@ sbi.worksheet.designer.seriesgroupingpanel.title = Series' grouping variable kn.error.export.timeout = The Export process timed out. Please try again in a while. +kn.generic.field = Field +kn.generic.expression = Expression kn.generic.search = Search +kn.cockpit.custom.code.unsafe = ERROR: Something inside the code is unsafe so the JS execution stopped.
Check your syntax or the widget documentation. +kn.cockpit.custom.editwidget = Edit custom chart widget + kn.cockpit.dataset.selection = Dataset Selection kn.cockpit.dataset.hasParameters = Parametrical kn.cockpit.dataset.label = Label @@ -1796,7 +1841,7 @@ kn.cockpit.dataset.type.file = File kn.cockpit.dataset.type.flat = Flat kn.cockpit.dataset.type.generic = Generic kn.cockpit.dataset.type.jclass = JClass -kn.cockpit.dataset.type.python = Python +kn.cockpit.dataset.type.python = Python/R kn.cockpit.dataset.type.qbe = Qbe kn.cockpit.dataset.type.query = Query kn.cockpit.dataset.type.rest = REST @@ -1810,6 +1855,7 @@ kn.cockpit.discovery.defaultsearchtype = Type kn.cockpit.discovery.edit = Edit Discovery widget kn.cockpit.discovery.enabledatatable = Enable Data Table kn.cockpit.discovery.facets.enable = Enable Selection on Facets +kn.cockpit.discovery.facets.enable.tooltip = Enabling this option, the click on facet will throw a cockpit selection instead of filtering the widget kn.cockpit.discovery.facets.max = Facets max number kn.cockpit.discovery.facets.width = Facets Column Width kn.cockpit.discovery.hidetextsearch = Hide text search @@ -1832,6 +1878,7 @@ kn.cockpit.html.tag7 = Selection kn.cockpit.html.tag8 = Calculator kn.cockpit.html.tag9 = Preview kn.cockpit.html.tag10 = Active selection +kn.cockpit.html.tag11 = Variables kn.cockpit.html.tag1.desc = This tag is used to show a field value from the selected dataset column. The optional attribute ROW make the tag show the field value of the specified row for that column. If a row is not specified the tag will show the first occurrence for the column. kn.cockpit.html.tag2.desc = This tag is used to show a parameter value from the ones available to the selected dataset. kn.cockpit.html.tag3.desc = This tag is used to repeat the html section delimited by the tag ending for every row in the dataset if the condition is verified. Set the condition to "true" to always show.The limit attribute limits the number of rows shown. Dynamic fields from dataset will take the value of the repeated row. @@ -1842,21 +1889,39 @@ kn.cockpit.html.tag7.desc = This tag is used to create an interactive element ge kn.cockpit.html.tag8.desc = This tag is used to calculate a result number from standard operations and other tags like kn-column and kn-parameter. kn.cockpit.html.tag9.desc = This tag is used to create an interactive element creating a link to a popup showing the specified dataset preview. kn.cockpit.html.tag10.desc = This tag is used to show the selected value of a column of the selected parameter. +kn.cockpit.html.tag11.desc = This tag is used to show the value of the selected variable. kn.cockpit.html.nodataset = No Dataset Selected kn.cockpit.html.nodatasetavailable = No Dataset Available kn.cockpit.python.configuration = Python Widget Configuration kn.cockpit.python.environment = Python environment +kn.cockpit.python.errorenvironment = Check environment configuration +kn.cockpit.python.errordataset = Check dataset configuration kn.cockpit.python.outputFileName = Output file name kn.cockpit.python.outputType = Output type kn.cockpit.python.outputVariableName = Output variable name kn.cockpit.python.pythonScript = Python script kn.cockpit.python.tag1.desc = This tag is used to select a specific column from the selected dataset -kn.cockpit.python.tag2.desc = This tag is used to choose a parameter value from the ones available from the selected dataset +kn.cockpit.python.tag2.desc = This tag is used to choose an analytical driver from the ones available kn.cockpit.python.nodataset = No Dataset Selected kn.cockpit.python.availabletags = Available Tags kn.cockpit.python.tag1 = Columns Data -kn.cockpit.python.tag2 = Parameters +kn.cockpit.python.tag2 = Drivers + +kn.cockpit.R.configuration = R Widget Configuration +kn.cockpit.R.environment = R environment +kn.cockpit.R.errorenvironment = Check environment configuration +kn.cockpit.R.errordataset = Check dataset configuration +kn.cockpit.R.outputFileName = Output file name +kn.cockpit.R.outputType = Output type +kn.cockpit.R.outputVariableName = Output variable name +kn.cockpit.R.RScript = R script +kn.cockpit.R.tag1.desc = This tag is used to select a specific column from the selected dataset +kn.cockpit.R.tag2.desc = This tag is used to choose an analytical driver from the ones available +kn.cockpit.R.nodataset = No Dataset Selected +kn.cockpit.R.availabletags = Available Tags +kn.cockpit.R.tag1 = Columns Data +kn.cockpit.R.tag2 = Drivers kn.cockpit.selector.selectall = Select/deselect All kn.cockpit.selector.select = Select @@ -1885,13 +1950,27 @@ kn.crossconfigurator.datasetparameters = Dataset Parameters kn.crossconfigurator.parameterchangedwarning = some parameters have been changed: kn.crossconfigurator.removedparameter = removed parameter kn.crossconfigurator.addedparameter = added parameter +kn.crossconfigurator.link.baseurl = Base url +kn.crossconfigurator.link.baseurl.hint = The url of the page that will be opened +kn.crossconfigurator.link.type = Link type +kn.crossconfigurator.link.type.blank = Open in new page +kn.crossconfigurator.link.type.samepage = Open in the same page +kn.crossconfigurator.link.urlparameters = Url Parameters +kn.crossconfigurator.link.noparameters = No parameters set, the link will be opened using the baseUrl only +kn.crossconfigurator.link.parameter.key = Parameter key +kn.crossconfigurator.link.parameter.type = Parameter type +kn.crossconfigurator.link.parameter.type.analyticaldriver = Analytical Driver +kn.crossconfigurator.link.parameter.type.json = JSON +kn.crossconfigurator.link.parameter.type.jwt = JWT kn.table.norows = No rows available kn.table.missingrequiredfields = Some required fields are missing kn.table.nomodality = No selector modality chosen kn.table.hideheader = Hide Header +kn.table.horizontalalign = Cell Horizontal Alignment kn.table.rowspan = Row Span kn.table.rowspan.tooltip = Collapse rows value together if the value of the column is the same +kn.table.verticalalign = Cell Vertical Alignment kn.variables = Variables kn.variables.action = Action @@ -1916,11 +1995,23 @@ kn.cockpit.functions.aggregation.count = Returns the number of rows that matches kn.cockpit.functions.aggregation.max = Returns the largest value of a numeric field. kn.cockpit.functions.aggregation.min = Returns the smallest value of a numeric field. kn.cockpit.functions.aggregation.sum = Returns the total sum of a numeric field. +kn.cockpit.functions.nullif = Returns NULL if the field value is equal to the selected value. +kn.cockpit.functions.total.avg = Returns the average value of the column. +kn.cockpit.functions.total.count = Returns the number of rows that matches the specific criteria in the column. +kn.cockpit.functions.total.max = Returns the largest value of the column. +kn.cockpit.functions.total.min = Returns the smallest value of the column. +kn.cockpit.functions.total.sum = Returns the total sum of the column. +kn.cockpit.functions.type.aggregation = aggregation +kn.cockpit.functions.type.functions = functions +kn.cockpit.functions.type.totals = column totals kn.cockpit.functions.argument.any = Field of any type or *. kn.cockpit.functions.argument.number = Field type Number. kn.cockpit.calculatedfield.validation.success = Validation Successful +kn.cockpit.calculatedfield.validation.division = A division has been detected. To avoid division by 0 please use the {0} function. +kn.cockpit.calculatedfield.validation.error.invalidalias = The alias name is invalid kn.cockpit.calculatedfield.validation.error.noalias = No alias name present kn.cockpit.calculatedfield.validation.error.noformula = No formula present kn.cockpit.calculatedfield.validation.error = Validation Error + kn.multicell.values = Cell values list \ No newline at end of file diff --git a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_es_ES.properties b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_es_ES.properties index 7c48726bddc..88321d5ab54 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_es_ES.properties +++ b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_es_ES.properties @@ -29,7 +29,6 @@ sbi.chartengine.axisstylepopup.labelParams.rotationOfLabelYAxis=Rotación sbi.chartengine.axisstylepopup.labelParams.title=Etiquetas sbi.chartengine.axisstylepopup.mainTickParams.tickColor=Color marcador sbi.chartengine.axisstylepopup.mainTickParams.tickLength=Longitud del marcador (px) -sbi.chartengine.axisstylepopup.mainTickParams.tickPixelInterval=Intervalo en píxeles del tick (px) sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.inside=Dentro sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.outside=Fuera sbi.chartengine.axisstylepopup.mainTickParams.tickPosition=Posición del marcador @@ -38,7 +37,6 @@ sbi.chartengine.axisstylepopup.mainTickParams.title=Marcador principal sbi.chartengine.axisstylepopup.majorgrid=grilla mayor sbi.chartengine.axisstylepopup.majorminorgrid.color=Color linea sbi.chartengine.axisstylepopup.minorgrid=grilla menor -sbi.chartengine.axisstylepopup.minorTickParams.minorTickInterval=Intervalo del marcador menor (px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickLength=Longitud del marcador menor (px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickPosition=Posición de marcador menor sbi.chartengine.axisstylepopup.minorTickParams.minorTickWidth=Ancho del marcador menor (px) diff --git a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_fr_FR.properties b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_fr_FR.properties index f61c1040c9a..8b953e1ece9 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_fr_FR.properties +++ b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_fr_FR.properties @@ -31,7 +31,6 @@ sbi.chartengine.axisstylepopup.labelParams.rotationOfLabelYAxis=Rotation sbi.chartengine.axisstylepopup.labelParams.title=étiquettes sbi.chartengine.axisstylepopup.mainTickParams.tickColor=Couleur de la tick sbi.chartengine.axisstylepopup.mainTickParams.tickLength=Longueur de la Tick (px) -sbi.chartengine.axisstylepopup.mainTickParams.tickPixelInterval=Intervalle de pixel Tick (px) sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.inside=Dans sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.outside=Extérieure sbi.chartengine.axisstylepopup.mainTickParams.tickPosition=Position de la tick @@ -41,7 +40,6 @@ sbi.chartengine.axisstylepopup.majorgrid=Grille Majeure sbi.chartengine.axisstylepopup.majorminorgrid.color=Couleur de ligne sbi.chartengine.axisstylepopup.minorgrid=Grille mineure sbi.chartengine.axisstylepopup.minorTickParams.enable.minorTickInterval=Activer l'intervalle de tick mineur -sbi.chartengine.axisstylepopup.minorTickParams.minorTickInterval=Intervalle de la tick inférieure (px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickLength=Longueur de la tick inférieure (px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickPosition=Position inférieure de la tick sbi.chartengine.axisstylepopup.minorTickParams.minorTickWidth=Largeure de la tick inférieure (px) diff --git a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_it_IT.properties b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_it_IT.properties index d2469d1efdb..6779e8b9677 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_it_IT.properties +++ b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_it_IT.properties @@ -189,6 +189,7 @@ sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMaxWidth=Larghezza sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMinHeight=Altezza minima sbi.chartengine.configuration.parallel.tooltip.parallelTooltipMinWidth=Larghezza minima sbi.chartengine.configuration.parallel.tooltip.parallelTooltipPadding=Distanziamento del testo +sbi.chartengine.configuration.parallel.tooltip.maxNumberOfRecords=Numero massimo di record da mostrare sbi.chartengine.configuration.parallel.tooltip.title=Configurazione del tooltip sbi.chartengine.configuration.parallelAxesLinesAxisColNamePadd.emptyText=Inserire distanziamento del nome dell'Asse sbi.chartengine.configuration.parallelAxesLinesBrushWidth.emptyText=Inserire larghezza del pennello @@ -468,6 +469,9 @@ sbi.chartengine.designer.tab.configuration.accessibility=Accessibilità sbi.chartengine.designer.tab.configuration.aria=Attivazione descrizioni ARIA sbi.chartengine.designer.tab.configuration.arialabel=Etichetta descrizione ARIA sbi.chartengine.designer.tab.configuration.3d=3D +sbi.chartengine.designer.tab.configuration.3d.available=Opzione disponibile solo se non utilizzi aggregazioni di categorie +sbi.chartengine.designer.tab.grouping.category=Opzione disponibile solo se non utilizzi date, funzioni di divisione o opzioni 3d. +sbi.chartengine.designer.tab.grouping.groupSeries=Opzione disponibile solo se non utilizzi date o aggregazioni di categorie. Può essere utilizzata solo una funzione di divisione. sbi.chartengine.designer.tab.configuration.absolute=Assoluto sbi.chartengine.designer.tab.configuration.advancedSerieBar=Configurazione avanzata della Serie sbi.chartengine.designer.tab.configuration.axislines=Line degli Assi @@ -491,6 +495,9 @@ sbi.chartengine.designer.tab.configuration.grouping.createsplitting=Impostazione sbi.chartengine.designer.tab.configuration.groupSeries=Seconda serie sbi.chartengine.designer.tab.configuration.groupSeriesCateg=Seconda categoria sbi.chartengine.designer.tab.configuration.seriesToUse=Serie da utilizzare su opzioni di categorie secondarie +sbi.chartengine.designer.tab.configuration.groupSeriesCateg.split=Dividi +sbi.chartengine.designer.tab.configuration.groupSeriesCateg.coloredCategory=Categoria colorata +sbi.chartengine.designer.tab.configuration.groupSeriesCateg.seriesToUse=Serie da utilizzare come opzione della seconda categoria sbi.chartengine.designer.tab.configuration.height=Altezza sbi.chartengine.designer.tab.configuration.horizontal=Orizzontale sbi.chartengine.designer.tab.configuration.italic=Corsivo @@ -704,6 +711,7 @@ sbi.cockpit.cross.outputParameter.column=Colonna sbi.cockpit.cross.outputParameter.dataset=Dataset sbi.cockpit.cross.outputParameter.dynamicvalue=Valore dinamico sbi.cockpit.cross.outputParameter.measurescolumnname=Nome colonna misure +sbi.cockpit.cross.outputParameter.selectedcolumnname=Nome della colonna selezionata sbi.cockpit.cross.outputParameter.type=Tipo sbi.cockpit.cross.outputParameter.value=Valore sbi.cockpit.cross.outputParameters=Lista parametri di output @@ -784,6 +792,7 @@ sbi.cockpit.editor.newwidget.description.html=Widget contenitore di codice HTML. sbi.cockpit.editor.newwidget.description.map=Mappa interattiva con livelli multipli di rappresentazione sbi.cockpit.editor.newwidget.description.selector=Widget selettore per filtrare rapidamente le categorie. sbi.cockpit.editor.newwidget.description.python=Scrivi il codice Python e crea la tua visualizzazione +sbi.cockpit.editor.newwidget.description.R=Scrivi il tuo script R per creare la tua visualizzazione personalizzata sbi.cockpit.editor.newwidget.description.discovery=Tabella avanzata con faccette per interagire con dataset di tipo Solr. sbi.cockpit.editor.newwidget.info=Seleziona una tipologia di widget per aggiungerla al foglio di lavoro attuale. sbi.cockpit.editor.newwidget.title=Seleziona nuovo widget @@ -933,9 +942,11 @@ sbi.cockpit.map.lonLatError=Errore nell'ottenimento di latitudine e longitudine sbi.cockpit.map.stringInvalid=Errore nell'ottenimento delle coordinate dalla colonna [ {0} ] con valore [ {1} ]. Il contenuto dovrebbe essere una STRINGA invece di un JSON. Controllare la configurazione. sbi.cockpit.map.typeLayerNotManaged=Livello di tipologia [ {0} ] non gestito\! sbi.cockpit.map.togglemapoptions=Abilita/disabilita opzioni mappa -sbi.cockpit.map.backgroundLayers=Livelli di sfondo +sbi.cockpit.map.genericConfiguration=Configurazione mappa sbi.cockpit.map.enableBaseLayer=Abilita livello base sbi.cockpit.map.selectBackgroundLayer=Seleziona livello di background +sbi.cockpit.map.zoomFactor=Fattore di zoom +sbi.cockpit.map.showScale=Mostra scala sbi.cockpit.map.edit.layerColType=Tipologia sbi.cockpit.map.edit.layerColName=Nome sbi.cockpit.map.edit.layerColLabel=Etichetta @@ -955,7 +966,37 @@ sbi.cockpit.map.edit.metadata.showOnDetail=Mostra nel popup di dettaglio sbi.cockpit.map.edit.metadata.showOnMap=Mostra sulla mappa sbi.cockpit.map.edit.metadata.showOnFilter=Mostra sul filtro sbi.cockpit.map.edit.metadata.modalColumn=Colonna modale +sbi.cockpit.map.edit.metadata.aggregateBy=Aggregato per sbi.cockpit.map.edit.metadata.threshold=Soglia +sbi.cockpit.map.edit.metadata.style=Stile +sbi.cockpit.map.edit.metadata.delete=Elimina +sbi.cockpit.map.edit.metadata.upate=Aggiorna +sbi.cockpit.map.edit.visualization.cardName=Tipi di visualizzazion +sbi.cockpit.map.edit.visualization.common.preview=Anteprima +sbi.cockpit.map.edit.visualization.header.clusters=Cluster +sbi.cockpit.map.edit.visualization.header.choroplet=Analisi +sbi.cockpit.map.edit.visualization.header.marker=Marker +sbi.cockpit.map.edit.visualization.header.heatmap=Configurazione Heatmap +sbi.cockpit.map.edit.visualization.cluster.radius=Raggio +sbi.cockpit.map.edit.visualization.cluster.fontSize=Dimensione font +sbi.cockpit.map.edit.visualization.cluster.fontColor=Colore font +sbi.cockpit.map.edit.visualization.cluster.backgroundColor=Colore sfondo +sbi.cockpit.map.edit.visualization.choroplet.classes=Metodo di classificazione +sbi.cockpit.map.edit.visualization.choroplet.classesByEqualIntervals=Classifica per intervalli uguali +sbi.cockpit.map.edit.visualization.choroplet.classesByQuantils=Classifica per quantili +sbi.cockpit.map.edit.visualization.choroplet.classesNumber=Numero classi +sbi.cockpit.map.edit.visualization.choroplet.fromColor=Dal colore +sbi.cockpit.map.edit.visualization.choroplet.toColor=Al colore +sbi.cockpit.map.edit.visualization.marker.defaultMarker=Marker di default +sbi.cockpit.map.edit.visualization.marker.iconMarker=Marker icona +sbi.cockpit.map.edit.visualization.marker.imageMarker=Marker immagine +sbi.cockpit.map.edit.visualization.marker.markerFromUrl=Immagine dal marker web +sbi.cockpit.map.edit.visualization.marker.fillColor=Colore +sbi.cockpit.map.edit.visualization.marker.borderColor=Colore del bordo +sbi.cockpit.map.edit.visualization.marker.scale=Scala (%) +sbi.cockpit.map.edit.visualization.marker.size=Dimensione (%) +sbi.cockpit.map.edit.visualization.heatmap.radius=Raggio +sbi.cockpit.map.edit.visualization.heatmap.blur=Sfocatura sbi.cockpit.msg.deletetab.msg=Confermi l'eliminazione dell'oggetto corrente? sbi.cockpit.msg.deletetab.title=Per favore confermare sbi.cockpit.msg.deletetaball.msg=Confermare l'eliminazione di tutti gli oggetti? @@ -977,6 +1018,9 @@ sbi.cockpit.pivot.messages.drop.attribute.remove=Drop qui per rimuovere sbi.cockpit.pivot.messages.drop.attribute=Drop Attributi sbi.cockpit.pivot.messages.drop.measure.remove=Drop qui per rimuovere sbi.cockpit.pivot.messages.drop.measure=Drop Misure +sbi.cockpit.pivot.messages.columns.info=Trascina uno o più attributi in questo contenitore per definire le colonne. +sbi.cockpit.pivot.messages.rows.info=Trascina uno o più attributi in questo contenitore per definire le categorie. +sbi.cockpit.pivot.messages.measures.info=Trascina una o più misure in questo contenitore per selezionare quelle che verranno mostrate. sbi.cockpit.pivot.rows=Righe sbi.cockpit.pivot.rows.height=Altezza Righe sbi.cockpit.pivot.subtotals=Subtotali @@ -1132,6 +1176,10 @@ sbi.cockpit.style.fontDecoration.lineThrough=Line through sbi.cockpit.style.fontDecoration.overline=Overline sbi.cockpit.style.fontDecoration.underline=Underline sbi.cockpit.style.fontSize.hint=Indicare px, rem o % come misura +sbi.cockpit.style.radius.bordertopleft=Arrotondamento bordo superiore sinistro +sbi.cockpit.style.radius.bordertopright=Arrotondamento bordo superiore destro +sbi.cockpit.style.radius.borderbottomleft=Arrotondamento bordo inferiore sinistro +sbi.cockpit.style.radius.borderbottomright=Arrotondamento bordo inferiore destro sbi.cockpit.style.radius.hint=Indicare ad esempio\: 5px sbi.cockpit.style.fontSize=Font Size sbi.cockpit.style.fontStyle.italic=Italico @@ -1184,6 +1232,7 @@ sbi.cockpit.table.alignment=Allineamento orizzontale cella sbi.cockpit.table.alternate=Righe alternate sbi.cockpit.table.alternate.evenrows=Colore righe pari sbi.cockpit.table.alternate.oddrows=Colore righe dispari +sbi.cockpit.table.alternate.warning=Attenzione\: le righe alternate verranno mostrate solo se non sono presenti altre personalizzazioni (Titoli e misure) sbi.cockpit.table.backgroundcolor=Colore di sfondo sbi.cockpit.table.backgroundthresholds=Background thresholds sbi.cockpit.table.chartalignment=Allineamento Grafico @@ -1228,6 +1277,7 @@ sbi.cockpit.table.missingdataset=Please Select a dataset sbi.cockpit.table.multiline=Permetti testo multilinea sbi.cockpit.table.multiselectioncolor=Colore di evidenziazione della selezione sbi.cockpit.table.nocolumns=Nessuna colonna selezionata. +sbi.cockpit.table.nodefault=Nessun valore predefinito impostato. sbi.cockpit.table.nomeasure=Nessuna misura da mostrare. sbi.cockpit.table.nothreshold=Nessun intervallo dichiarato sbi.cockpit.table.pinned=Blocco colonna @@ -1263,6 +1313,9 @@ sbi.cockpit.widget.pivot=CrossTab sbi.cockpit.widget.python.environment=Ambiente sbi.cockpit.widget.python.library=Libreria sbi.cockpit.widget.python.version=Versione +sbi.cockpit.widget.R.environment=Ambiente +sbi.cockpit.widget.R.library=Libreria +sbi.cockpit.widget.R.version=Versione sbi.cockpit.widget.selection=Selezione sbi.cockpit.widget.selection.message=Messaggio sbi.cockpit.widget.selection.messagehint=Se lasciato vuoto il messaggio di default sarà\: "Nessuna selezione attiva" @@ -1290,6 +1343,7 @@ sbi.cockpit.widget.table.rows=Righe sbi.cockpit.widget.table.summary=Totale sbi.cockpit.widget.table.summary.add=Aggiungi sbi.cockpit.widget.table.summary.addtooltip=Aggiungi riga di riepilogo +sbi.cockpit.widget.table.summary.noPinnedColumnsWarning=Attenzione\: non è stata definita nessuna colonna bloccata. Non vorrà mostrata nessuna label. sbi.cockpit.widget.text=Testo sbi.cockpit.widget.text.editor=Editor di testo sbi.cockpit.widget.text.missingtext=Il testo è vuoto\! @@ -1455,6 +1509,8 @@ sbi.cockpit.widgets.table.column.hideall=Nascondi tutte le colonne sbi.cockpit.widgets.table.column.type=Tipo sbi.cockpit.widgets.table.column.aggregation=Funzione di aggregazione sbi.cockpit.widgets.table.column.showall=Mostra tutte le colonne +sbi.cockpit.widgets.table.column.summaryAggregation=Aggregazione della riga dei totali +sbi.cockpit.widgets.table.column.summaryDefaultAggregation=Aggregazione di default della colonna sbi.cockpit.widgets.table.column.summaryfunction=Funzione di riepilogo sbi.cockpit.widgets.table.confirm.delete=Conferma cancellazione sbi.cockpit.widgets.table.confirm.delete.text=Sei sicuro di voler cancellare tutte le colonne? @@ -1463,6 +1519,11 @@ sbi.cockpit.widgets.table.modalselectioncolumn=Colonna per selezione modale sbi.cockpit.widgets.table.nodata.default=Non ci sono dati disponibili sbi.cockpit.widgets.table.nodata.label=Non mostrare il messaggio "Nessun dato disponibile" sbi.cockpit.widgets.table.nodata.message=Messaggio "Nessun dato disponibile" custom +sbi.cockpit.widgets.table.pagination.first=Prima +sbi.cockpit.widgets.table.pagination.last=Ultima +sbi.cockpit.widgets.table.pagination.next=Prossima +sbi.cockpit.widgets.table.pagination.previous=Precedente +sbi.cockpit.widgets.table.pagination.to=a sbi.cockpit.widgets.table.pagination.of=di sbi.cockpit.widgets.table.pagination.page=Pagina Sbi.cockpit.widgets.table.QueryFieldsContainerPanel.info=Definisci col mouse l'ordine di apparizione dei campi, con un doppio click su una misura si definisce l'aggregazione. per cancellare un campo premere Canc @@ -1581,6 +1642,7 @@ sbi.data.editor.association.AssociationEditor.notValidAssociation=L'associazione sbi.data.editor.association.AssociationEditor.warning=Avviso sbi.data.editor.association.AssociationEditor.warning.message=Errore di Validazione. Verificare i campi necessari\! sbi.data.editor.association.AssociationEditor.warning.misingChartDesigner=È necessario usare il designer per creare il template di un grafico, per poter salvare il widget\! +sbi.data.editor.association.AssociationEditor.warning.deletingCFOnSerie=Non puoi eliminare questo campo calcolato essendo utilizzato in una serie del grafico. Devi prima rimuoverlo dalla serie. sbi.ds.filterLabel=Filtra per ... sbi.ds.moreRecent=Recenti sbi.ds.orderComboLabel=Ordina per ... @@ -1746,7 +1808,11 @@ sbi.worksheet.designer.chartseriespanel.title=Serie sbi.worksheet.designer.chartseriespanel.tools.tt.removeall=Rimuovi tutto sbi.worksheet.designer.seriesgroupingpanel.title=Variabile del raggruppamento delle serie kn.error.export.timeout=Tempo scaduto per il processo di esportazione. Riprova tra qualche istante. +kn.generic.field=Campo +kn.generic.expression=Espressione kn.generic.search=Cerca +kn.cockpit.custom.code.unsafe=Errore\: Qualcosa all'interno del codice è stato identificato come non sicuro e l'esecuzione del codice JS è stata interrotta.
Controlla la sintassi o la documentazione del widget. +kn.cockpit.custom.editwidget=Modifica widget grafico personalizzato kn.cockpit.dataset.selection=Selezione Dataset kn.cockpit.dataset.hasParameters=Colonna parametrica kn.cockpit.dataset.label=Etichetta @@ -1759,7 +1825,7 @@ kn.cockpit.dataset.type.file=File kn.cockpit.dataset.type.flat=Flat kn.cockpit.dataset.type.generic=Generico kn.cockpit.dataset.type.jclass=JClass -kn.cockpit.dataset.type.python=Python +kn.cockpit.dataset.type.python=Python/R kn.cockpit.dataset.type.qbe=Qbe kn.cockpit.dataset.type.query=Query kn.cockpit.dataset.type.rest=REST @@ -1772,6 +1838,7 @@ kn.cockpit.discovery.defaultsearchtype=Tipologia kn.cockpit.discovery.edit=Modifica widget discovery kn.cockpit.discovery.enabledatatable=Abilita griglia dati kn.cockpit.discovery.facets.enable=Abilita selezione sulle faccette +kn.cockpit.discovery.facets.enable.tooltip=Abilitando questa opzione, il click sulle faccette lancerà una selezione sul cockpit invece che un filtro sul widget. kn.cockpit.discovery.facets.max=Massimo numero di faccette kn.cockpit.discovery.facets.width=Larghezza colonna faccette kn.cockpit.discovery.hidetextsearch=Nascondi ricerca testuale @@ -1793,6 +1860,7 @@ kn.cockpit.html.tag7=Selezione kn.cockpit.html.tag8=Calcolo kn.cockpit.html.tag9=Preview kn.cockpit.html.tag10=Selezioni attive +kn.cockpit.html.tag11=Variabili kn.cockpit.html.tag1.desc=Questo tag viene utilizzato per mostrare un valore del campo dalla colonna del data set selezionato. L'attributo opzionale ROW fa sì che il tag mostri il valore del campo della riga specificata per quella colonna. Se una riga non viene specificata, il tag mostrerà la prima occorrenza per la colonna. kn.cockpit.html.tag2.desc=Questo tag viene utilizzato per mostrare un valore di parametro tra quelli disponibili per il data set selezionato. kn.cockpit.html.tag3.desc=Questo tag viene utilizzato per ripetere la sezione HTML delimitata dal tag che termina per ogni riga nel data set, se la condizione è verificata. Imposta la condizione su "true" per mostrare sempre. L'attributo "limit" limita il numero di righe mostrate. I campi dinamici dal data set assumeranno il valore della riga ripetuta. @@ -1803,10 +1871,13 @@ kn.cockpit.html.tag7.desc=Questo tag è usato per creare un elemento interattivo kn.cockpit.html.tag8.desc=Questo tag è usato per calcolare un risultato numerico attraverso operatori standard e tag come kn-column o kn-parameter. kn.cockpit.html.tag9.desc=Questo tag è usato per creare un elemento interattivo che scateni una popup con la preview del dataset specificato. kn.cockpit.html.tag10.desc=Questo tag è utilizzato per mostrare il valore di una colonna del parametro selezionato +kn.cockpit.html.tag11.desc=Questo tag è usato per visualizzare il valore della variabile selezionata kn.cockpit.html.nodataset=Nessun dataset selezionato kn.cockpit.html.nodatasetavailable=Nessun dataset disponibile kn.cockpit.python.configuration=Configurazione widget Python kn.cockpit.python.environment=Ambiente Python +kn.cockpit.python.errorenvironment=Controlla la configurazione dell'ambiente +kn.cockpit.python.errordataset=Controlla la configurazione del dataset kn.cockpit.python.outputFileName=Nome file di output kn.cockpit.python.outputType=Tipo di output kn.cockpit.python.outputVariableName=Nome variabile di output @@ -1816,7 +1887,21 @@ kn.cockpit.python.tag2.desc=Questo tag viene utilizzato per scegliere il valore kn.cockpit.python.nodataset=Nessun dataset selezionato kn.cockpit.python.availabletags=Tag disponibili kn.cockpit.python.tag1=Dati colonna -kn.cockpit.python.tag2=Parameters +kn.cockpit.python.tag2=Parametri +kn.cockpit.R.configuration=Configurazione widget R +kn.cockpit.R.environment=Ambiente R +kn.cockpit.R.errorenvironment=Controlla la configurazione dell'ambiente +kn.cockpit.R.errordataset=Controlla la configurazione del dataset +kn.cockpit.R.outputFileName=Nome file di output +kn.cockpit.R.outputType=Tipo di output +kn.cockpit.R.outputVariableName=Nome variabile di output +kn.cockpit.R.RScript=Script R +kn.cockpit.R.tag1.desc=Questo tag è utilizzato per selezionare una specifica colonna dal dataset selezionato +kn.cockpit.R.tag2.desc=Questo tag è utilizzato per scegliere un parametro tra quelli disponibili +kn.cockpit.R.nodataset=Nessun dataset selezionato +kn.cockpit.R.availabletags=Tag disponibili +kn.cockpit.R.tag1=Dati della colonna +kn.cockpit.R.tag2=Parametri kn.cockpit.selector.selectall=Seleziona/Deseleziona tutto kn.cockpit.selector.select=Seleziona kn.cockpit.selector.cancel=Annulla @@ -1842,10 +1927,26 @@ kn.crossconfigurator.datasetparameters=Parametri del dataset kn.crossconfigurator.parameterchangedwarning=Alcuni parametri sono stati cambiati\: kn.crossconfigurator.removedparameter=parametro rimosso kn.crossconfigurator.addedparameter=parametro aggiunto +kn.crossconfigurator.link.baseurl=Base url +kn.crossconfigurator.link.baseurl.hint=URL della pagina che verrà aperta +kn.crossconfigurator.link.type=Tipo di collegamento +kn.crossconfigurator.link.type.blank=Apri in una nuova pagina +kn.crossconfigurator.link.type.samepage=Apri nella stessa pagina +kn.crossconfigurator.link.urlparameters=Parametri dell'URL +kn.crossconfigurator.link.noparameters=Nessun parametro impostato, il collegamento verrà aperto utilizzando solo baseUrl +kn.crossconfigurator.link.parameter.key=Nome del parametro +kn.crossconfigurator.link.parameter.type=Tipologia del parametro +kn.crossconfigurator.link.parameter.type.analyticaldriver=Driver analitico +kn.crossconfigurator.link.parameter.type.json=JSON +kn.crossconfigurator.link.parameter.type.jwt=JWT kn.table.norows=Non ci sono dati disponibili kn.table.missingrequiredfields=Alcuni campi obbligatori sono mancanti kn.table.nomodality=Nessuna modalità di selettore selezionata kn.table.hideheader=Nascondi testata +kn.table.horizontalalign=Allineamento orizzontale cella +kn.table.rowspan=Raggruppa righe +kn.table.rowspan.tooltip=Collassa righe se il valore della colonna è lo stesso +kn.table.verticalalign=Allineamento verticale cella kn.variables=Variabili kn.variables.action=Azione kn.variables.addvariable=Aggiungi Variabile @@ -1868,9 +1969,20 @@ kn.cockpit.functions.aggregation.count=Restituisce il numero di righe che corris kn.cockpit.functions.aggregation.max=Restituisce il valore più grande di un campo numerico kn.cockpit.functions.aggregation.min=Restituisce il valore più piccolo di un campo numerico kn.cockpit.functions.aggregation.sum=Restituisce il toale di un campo numerico +kn.cockpit.functions.nullif=Restituisce NULL se il valore del campo è uguale al valore selezionato. +kn.cockpit.functions.total.avg=Restituisce il valore medio della colonna. +kn.cockpit.functions.total.count=Restituisce il numero di righe che corrisponde ai criteri specifici nella colonna. +kn.cockpit.functions.total.max=Restituisce il valore più grande della colonna. +kn.cockpit.functions.total.min=Restituisce il valore più piccolo della colonna. +kn.cockpit.functions.total.sum=Restituisce la somma totale della colonna. +kn.cockpit.functions.type.aggregation=Aggregazione +kn.cockpit.functions.type.functions=Funzioni +kn.cockpit.functions.type.totals=Totali colonne kn.cockpit.functions.argument.any=Campi di ogni tipo o *. kn.cockpit.functions.argument.number=Campo di tipo Numero kn.cockpit.calculatedfield.validation.success=Validazione riuscita +kn.cockpit.calculatedfield.validation.division=È stata rilevata una divisione. Per evitare la divisione per 0, utilizzare la funzione {0}. +kn.cockpit.calculatedfield.validation.error.invalidalias=Nome alias non valido kn.cockpit.calculatedfield.validation.error.noalias=Nessun alias presente per il campo calcolato kn.cockpit.calculatedfield.validation.error.noformula=Formula non presente kn.cockpit.calculatedfield.validation.error=Errore di validazione diff --git a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_zh_Hans_CN.properties b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_zh_Hans_CN.properties index 70cd79cff2e..737c9e339f8 100644 --- a/knowagecockpitengine/src/main/webapp/js/src/messages/messages_zh_Hans_CN.properties +++ b/knowagecockpitengine/src/main/webapp/js/src/messages/messages_zh_Hans_CN.properties @@ -31,7 +31,6 @@ sbi.chartengine.axisstylepopup.labelParams.rotationOfLabelYAxis=旋转 sbi.chartengine.axisstylepopup.labelParams.title=标签 sbi.chartengine.axisstylepopup.mainTickParams.tickColor=记号颜色 sbi.chartengine.axisstylepopup.mainTickParams.tickLength=记号长度(px) -sbi.chartengine.axisstylepopup.mainTickParams.tickPixelInterval=记号像素间距(px) sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.inside=在里面 sbi.chartengine.axisstylepopup.mainTickParams.tickPosition.outside=在外面 sbi.chartengine.axisstylepopup.mainTickParams.tickPosition=记号位置 @@ -41,7 +40,6 @@ sbi.chartengine.axisstylepopup.majorgrid=主要网格 sbi.chartengine.axisstylepopup.majorminorgrid.color=行颜色 sbi.chartengine.axisstylepopup.minorgrid=次要网格 sbi.chartengine.axisstylepopup.minorTickParams.enable.minorTickInterval=启用次要记号间距 -sbi.chartengine.axisstylepopup.minorTickParams.minorTickInterval=次要记号间距(px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickLength=次要记号长度(px) sbi.chartengine.axisstylepopup.minorTickParams.minorTickPosition=次要记号位置 sbi.chartengine.axisstylepopup.minorTickParams.minorTickWidth=次要记号宽度(px) @@ -930,7 +928,6 @@ sbi.cockpit.map.lonLatError=从[{0}]列获取值[{1}]的经度和纬度时出错 sbi.cockpit.map.stringInvalid=从[{0}]列获取值[{1}]的坐标时出错。内容应该是字符串而不是JSON。请检查配置。 sbi.cockpit.map.typeLayerNotManaged=类型[{0}]的层未被管理\! sbi.cockpit.map.togglemapoptions=切换地图选型 -sbi.cockpit.map.backgroundLayers=背景图层 sbi.cockpit.map.enableBaseLayer=启用基础图层 sbi.cockpit.map.selectBackgroundLayer=选择背景图层 sbi.cockpit.map.edit.layerColType=类型 diff --git a/knowagecockpitengine/src/main/webapp/js/tests/cockpitModule_customWidgetServices.test.js b/knowagecockpitengine/src/main/webapp/js/tests/cockpitModule_customWidgetServices.test.js new file mode 100644 index 00000000000..00072ff16f9 --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/js/tests/cockpitModule_customWidgetServices.test.js @@ -0,0 +1,169 @@ +describe("customWidgetAPI", function() { + var customChartDatastore; + var mockData = {"metaData":{"totalProperty":"results","root":"rows","id":"id","fields":["recNo",{"name":"column_1","header":"QUARTER","dataIndex":"column_1","type":"string","multiValue":false},{"name":"column_2","header":"THE_DATE","dataIndex":"column_2","type":"date","subtype":"timestamp","dateFormat":"d/m/Y H:i:s.uuu","dateFormatJava":"dd/MM/yyyy HH:mm:ss.SSS","multiValue":false},{"name":"column_3","header":"STORE_ID","dataIndex":"column_3","type":"float","multiValue":false},{"name":"column_4","header":"PRODUCT_FAMILY","dataIndex":"column_4","type":"string","multiValue":false},{"name":"column_5","header":"UNIT_SALES","dataIndex":"column_5","type":"float","multiValue":false},{"name":"column_6","header":"STORE_COST","dataIndex":"column_6","type":"float","multiValue":false}],"cacheDate":"2020-03-05 10:33:36.213"},"results":3928,"rows":[{"id":1,"column_1":"Q1","column_2":"28/01/1998 00:00:00.000","column_3":"1","column_4":"Drink","column_5":"48","column_6":"38.0323"},{"id":2,"column_1":"Q2","column_2":"19/04/1998 00:00:00.000","column_3":"1","column_4":"Drink","column_5":"44","column_6":"36.6181"},{"id":3,"column_1":"Q1","column_2":"27/03/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"75","column_6":"70.7084"},{"id":4,"column_1":"Q2","column_2":"18/04/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"112","column_6":"86.7598"},{"id":5,"column_1":"Q4","column_2":"24/11/1998 00:00:00.000","column_3":"1","column_4":"Food","column_5":"303","column_6":"274.2339"},{"id":6,"column_1":"Q4","column_2":"14/11/1998 00:00:00.000","column_3":"1","column_4":"Non-Consumable","column_5":"80","column_6":"65.998"},{"id":7,"column_1":"Q3","column_2":"25/08/1998 00:00:00.000","column_3":"2","column_4":"Food","column_5":"36","column_6":"31.5318"},{"id":8,"column_1":"Q1","column_2":"02/03/1998 00:00:00.000","column_3":"3","column_4":"Drink","column_5":"49","column_6":"37.6628"},{"id":9,"column_1":"Q2","column_2":"05/06/1998 00:00:00.000","column_3":"3","column_4":"Drink","column_5":"31","column_6":"27.965"},{"id":10,"column_1":"Q3","column_2":"13/07/1998 00:00:00.000","column_3":"3","column_4":"Food","column_5":"220","column_6":"189.1403"}]}; + beforeEach(function(){ + module(function($provide){ + $provide.service('datastoreService', function(){}); + }); + module('customWidgetAPI'); + }); + + beforeEach(inject(function(datastore){ + customChartDatastore = datastore + customChartDatastore.setData(mockData) + })); + + it('should set data',function (){ + expect(customChartDatastore.data.results).toBeDefined() + }); + + describe("getDataArray method", function() { + + it('should contain same number of datastore items',function (){ + expect(customChartDatastore.getDataArray(function(record){ + return { + y: record.UNIT_SALES, + name: record.QUARTER + } + }).length).toBe(mockData.rows.length) + }); + }); + + it('should contain columns "QUARTER" list',function (){ + expect(customChartDatastore.sort('QUARTER').getColumn('QUARTER')).toEqual(["Q1","Q2","Q3","Q4"]) + }); + + describe("filter method", function() { + it('should leave selected datastore objects with a single filter',function (){ + var temp = customChartDatastore.filter({'QUARTER':'Q1'}).getDataArray(function(record){ + return record.QUARTER + }) + expect(temp.indexOf('Q1')).not.toEqual(-1) + expect(temp.indexOf('Q2')).toEqual(-1) + }); + + it('should leave selected datastore objects with multiple filters',function (){ + var temp = customChartDatastore.filter({'QUARTER':'Q1','STORE_ID':'1'}).getDataArray(function(record){ + return { + quarter: record.QUARTER, + id: record.STORE_ID + } + }) + expect(temp.length).toEqual(2) + expect(temp[0].id).toEqual('1') + }); + }) + + describe("sort method", function() { + it('should sort datastore array of object correctly',function (){ + var temp = customChartDatastore.sort('STORE_ID').getDataArray(function(record){ + return { + store: record.STORE_ID, + quarter: record.QUARTER, + sales: record.UNIT_SALES + } + }) + expect(temp[0].store).toEqual('1') + }); + + it('should sort with object datastore array of object correctly',function (){ + var temp = customChartDatastore.sort({'STORE_ID':'desc'}).getDataArray(function(record){ + return { + store: record.STORE_ID, + quarter: record.QUARTER, + sales: record.UNIT_SALES + } + }) + expect(temp[0].store).toEqual('3'); + }); + + it('should sort datastore array of array correctly',function (){ + var temp = customChartDatastore.sort('STORE_ID').getDataArray(function(record){ + return [record.STORE_ID, record.QUARTER] + }) + expect(temp[0][0]).toEqual('1') + }); + + it('should sort datastore array correctly',function (){ + var temp = customChartDatastore.sort('STORE_ID').getDataArray(function(record){ + return record.STORE_ID + }) + expect(temp[0]).toEqual('1') + }); + }) + + describe("hierarchy method", function() { + it('should return a data tree when not defining measures',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY']}) + expect(temp.tree).toBeDefined() + }) + + it('should return a data tree when defining measures',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}) + expect(temp).toBeDefined() + }) + + it('should not return a two levels tree when just one is requested',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER'],'measures':{'UNIT_SALES':'SUM'}}) + expect(temp.tree[0].children[0]).not.toBeDefined() + }) + + it('should return children aggregated measures',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}) + expect(temp.tree[0].children[0].UNIT_SALES + temp.tree[0].children[1].UNIT_SALES).toEqual(temp.tree[0].UNIT_SALES) + }) + + it('should return a specific hierarchy\'s child(node)',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0) + expect(temp).toBeDefined() + expect(temp.name).toEqual('Q1') + }) + + it('should return a measure value for a specific hierarchy\'s child(node)',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0).getValue('UNIT_SALES') + expect(temp).toBeDefined() + expect(temp).toEqual(123) + }) + + it('should return a specific node\'s child',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0).getChild(0) + expect(temp).toBeDefined() + expect(temp.name).toEqual('Drink') + expect(temp.children.length).toEqual(0) + }) + + it('should return an array of node\'s children',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0).getChildren() + expect(temp).toBeDefined() + expect(temp.length).toBeGreaterThan(0) + expect(temp[0].name).toEqual('Drink') + }) + + it('should return an array of nodes of a specific level',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getLevel(0) + expect(temp).toBeDefined() + expect(temp.length).toBeGreaterThan(0) + expect(temp[0].children[0].name).toEqual('Drink') + }) + + it('should return an array of nodes of a different specific level',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getLevel(1) + expect(temp).toBeDefined() + expect(temp.length).toBeGreaterThan(0) + expect(temp[0].name).toEqual('Drink') + }) + + it('should return a node parent of specific child',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0).getChild(0).getParent(); + expect(temp.name).toEqual('Q1') + }) + + it('should return an array of node siblings to a specific child',function (){ + var temp = customChartDatastore.hierarchy({'levels':['QUARTER','PRODUCT_FAMILY'],'measures':{'UNIT_SALES':'SUM'}}).getChild(0).getChild(0).getSiblings(); + expect(temp.length).toEqual(2) + }) + + }) +}); + + diff --git a/knowagecockpitengine/src/main/webapp/karma.conf.js b/knowagecockpitengine/src/main/webapp/karma.conf.js new file mode 100644 index 00000000000..f932414116c --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/karma.conf.js @@ -0,0 +1,81 @@ +// Karma configuration +// Generated on Wed Mar 25 2020 18:00:09 GMT+0100 (GMT+01:00) + +module.exports = function(config) { + config.set({ + + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine'], + + + // list of files / patterns to load in the browser + files: [ + 'node_modules/angular/angular.js', + 'node_modules/angular-mocks/angular-mocks.js', + 'js/src/angular_1.4/cockpit/services/cockpitModule_customWidgetServices.js', + 'js/tests/*.test.js', + ], + + + // list of files / patterns to exclude + exclude: [ + ], + + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + }, + + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['progress'], + + + // web server port + port: 9876, + + + // enable / disable colors in the output (reporters and logs) + colors: true, + + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: [ + 'ChromeDebugging' + ], + + customLaunchers: { + ChromeDebugging: { + base: 'Chrome', + flags: [ '--remote-debugging-port=9333' ] + } + }, + + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity + }) +} diff --git a/knowagecockpitengine/src/main/webapp/package.json b/knowagecockpitengine/src/main/webapp/package.json new file mode 100644 index 00000000000..7e465f3b1ad --- /dev/null +++ b/knowagecockpitengine/src/main/webapp/package.json @@ -0,0 +1,25 @@ +{ + "name": "knowagecockpitengine", + "version": "7.2.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "karma start" + }, + "author": "knowage labs ", + "license": "AGPL-3.0", + "bugs": { + "url": "https://github.com/KnowageLabs/Knowage-Server/issues" + }, + "devDependencies": { + "angular": "^1.7.9", + "angular-mocks": "^1.7.9", + "jasmine": "^3.5.0", + "jsonpath": "^1.0.2", + "karma": "^4.4.1", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^1.3.0", + "karma-ie-launcher": "^1.0.0", + "karma-jasmine": "^3.1.1" + } +} diff --git a/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 23bafa6cf5c..00000000000 --- a/knowagecommonjengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache { - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config: allConfig ) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: "+config.getLabel() +" / "+config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine",e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagecommonjengine/src/main/webapp/META-INF/context.xml b/knowagecommonjengine/src/main/webapp/META-INF/context.xml index 5186babe95f..b86e5af8dac 100644 --- a/knowagecommonjengine/src/main/webapp/META-INF/context.xml +++ b/knowagecommonjengine/src/main/webapp/META-INF/context.xml @@ -10,4 +10,4 @@ - + diff --git a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/BIObjectDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/BIObjectDAOHibImpl.java index 8ea97c48c3e..821fd02d759 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/BIObjectDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/BIObjectDAOHibImpl.java @@ -30,14 +30,20 @@ import java.util.Map; import java.util.Set; -import it.eng.spagobi.analiticalmodel.document.util.EscapedLikeRestrictions; import org.apache.log4j.Logger; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; -import org.hibernate.criterion.*; +import org.hibernate.criterion.Criterion; +import org.hibernate.criterion.Disjunction; +import org.hibernate.criterion.Expression; +import org.hibernate.criterion.MatchMode; +import org.hibernate.criterion.Order; +import org.hibernate.criterion.Projections; +import org.hibernate.criterion.Property; +import org.hibernate.criterion.Restrictions; import org.hibernate.transform.Transformers; import org.safehaus.uuid.UUID; import org.safehaus.uuid.UUIDGenerator; @@ -63,6 +69,7 @@ import it.eng.spagobi.analiticalmodel.document.metadata.SbiObjTemplates; import it.eng.spagobi.analiticalmodel.document.metadata.SbiObjects; import it.eng.spagobi.analiticalmodel.document.util.DocumentCompositionUtil; +import it.eng.spagobi.analiticalmodel.document.util.EscapedLikeRestrictions; import it.eng.spagobi.analiticalmodel.functionalitytree.metadata.SbiFunctions; import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.BIObjectParameter; import it.eng.spagobi.behaviouralmodel.analyticaldriver.bo.Parameter; @@ -132,13 +139,10 @@ public class BIObjectDAOHibImpl extends AbstractHibernateDAO implements IBIObjec /** * Load bi object for execution by id and role. * - * @param id - * the id - * @param role - * the role + * @param id the id + * @param role the role * @return the BI object - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#loadBIObjectForExecutionByIdAndRole(java.lang.Integer, java.lang.String) */ @Override @@ -211,11 +215,9 @@ public BIObject loadBIObjectForExecutionByIdAndRole(Integer id, String role) thr /** * Load bi object by id. * - * @param biObjectID - * the bi object id + * @param biObjectID the bi object id * @return the BI object - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#loadBIObjectById(java.lang.Integer) */ @Override @@ -252,11 +254,9 @@ public BIObject loadBIObjectById(Integer biObjectID) throws EMFUserError { /** * Load bi object for detail. * - * @param id - * the id + * @param id the id * @return the BI object - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#loadBIObjectForDetail(java.lang.Integer) */ @Override @@ -299,11 +299,9 @@ public BIObject loadBIObjectForDetail(Integer id) throws EMFUserError { /** * Load bi object by label. * - * @param label - * the label + * @param label the label * @return the BI object - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#loadBIObjectByLabel(java.lang.String) */ @Override @@ -344,11 +342,9 @@ public BIObject loadBIObjectByLabel(String label) throws EMFUserError { /** * Load bi object for tree. * - * @param id - * the id + * @param id the id * @return the BI object - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#loadBIObjectForTree(java.lang.Integer) */ @Override @@ -393,10 +389,8 @@ public BIObject loadBIObjectForTree(Integer id) throws EMFUserError { /** * Modify bi object. * - * @param obj - * the obj - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObject(it.eng.spagobi.analiticalmodel.document.bo.BIObject) */ @Override @@ -407,12 +401,9 @@ public void modifyBIObject(BIObject obj) throws EMFUserError { /** * Modify bi object. * - * @param obj - * the obj - * @param loadParsDC - * boolean for management Document Composition params - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param loadParsDC boolean for management Document Composition params + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObject(it.eng.spagobi.analiticalmodel.document.bo.BIObject) */ @Override @@ -423,12 +414,9 @@ public void modifyBIObject(BIObject obj, boolean loadParsDC) throws EMFUserError /** * Modify bi object. * - * @param obj - * the obj - * @param objTemp - * the obj temp - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param objTemp the obj temp + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObjectWithoutVersioning(it.eng.spagobi.analiticalmodel.document.bo.BIObject) */ @Override @@ -439,12 +427,9 @@ public void modifyBIObject(BIObject obj, ObjTemplate objTemp) throws EMFUserErro /** * Modify bi object (specially provided for custom-made output category parameters for the SUNBURST chart). * - * @param obj - * the obj - * @param objTemp - * the obj temp - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param objTemp the obj temp + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObjectWithoutVersioning(it.eng.spagobi.analiticalmodel.document.bo.BIObject) * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ @@ -456,12 +441,9 @@ public void modifyBIObject(BIObject obj, ObjTemplate objTemp, List categories) t /** * Modify bi object (for special chart types, that need exclusion of some of default output parameters). Example: WORDCLOUD, PARALLEL and CHORD chart types. * - * @param obj - * the obj - * @param objTemp - * the obj temp - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param objTemp the obj temp + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObjectWithoutVersioning(it.eng.spagobi.analiticalmodel.document.bo.BIObject) * @author Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ @@ -473,14 +455,10 @@ public void modifyBIObject(BIObject obj, ObjTemplate objTemp, String specificCha /** * Modify bi object. * - * @param obj - * the obj - * @param objTemp - * the obj temp - * @param loadParsDC - * boolean for management Document Composition params - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param objTemp the obj temp + * @param loadParsDC boolean for management Document Composition params + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#modifyBIObjectWithoutVersioning(it.eng.spagobi.analiticalmodel.document.bo.BIObject) */ @Override @@ -492,12 +470,9 @@ public void modifyBIObject(BIObject obj, ObjTemplate objTemp, boolean loadParsDC /** * Updates the biobject data into database. * - * @param biObject - * The BI Object as input - * @param objTemp - * The BIObject template - * @throws EMFUserError - * If any exception occurred + * @param biObject The BI Object as input + * @param objTemp The BIObject template + * @throws EMFUserError If any exception occurred */ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean loadParsDC) throws EMFUserError { logger.debug("IN"); @@ -641,6 +616,7 @@ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean load if (loadParsDC && (oldTemp == null || objTemp.getId() == null || objTemp.getId().compareTo(oldTemp.getId()) != 0)) { insertParametersDocComposition(biObject, objTemp, true); } + } catch (Exception e) { logger.error("Error during creation of document composition parameters : ", e); throw new EMFUserError(EMFErrorSeverity.ERROR, e.getMessage()); @@ -669,12 +645,9 @@ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean load /** * Updates the biobject data into database (specially provided for custom-made output category parameters for the SUNBURST chart). * - * @param biObject - * The BI Object as input - * @param objTemp - * The BIObject template - * @throws EMFUserError - * If any exception occurred + * @param biObject The BI Object as input + * @param objTemp The BIObject template + * @throws EMFUserError If any exception occurred */ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean loadParsDC, List categories) throws EMFUserError { logger.debug("IN"); @@ -824,12 +797,9 @@ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean load * Updates the biobject data into database (for special chart types, that need exclusion of some of default output parameters). Example: WORDCLOUD, PARALLEL * and CHORD chart types. * - * @param biObject - * The BI Object as input - * @param objTemp - * The BIObject template - * @throws EMFUserError - * If any exception occurred + * @param biObject The BI Object as input + * @param objTemp The BIObject template + * @throws EMFUserError If any exception occurred */ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean loadParsDC, String specificChartTypes) throws EMFUserError { logger.debug("IN"); @@ -974,12 +944,9 @@ private void internalModify(BIObject biObject, ObjTemplate objTemp, boolean load * Implements the query to insert a BIObject and its template. All information needed is stored into the input BIObject and * ObjTemplate objects. * - * @param obj - * The object containing all insert information - * @param objTemp - * The template of the biobject - * @throws EMFUserError - * If an Exception occurred + * @param obj The object containing all insert information + * @param objTemp The template of the biobject + * @throws EMFUserError If an Exception occurred */ @Override public void insertBIObject(BIObject obj, ObjTemplate objTemp, boolean loadParsDC) throws EMFUserError { @@ -989,10 +956,8 @@ public void insertBIObject(BIObject obj, ObjTemplate objTemp, boolean loadParsDC /** * Implements the query to insert a BIObject. All information needed is stored into the input BIObject object. * - * @param obj - * The object containing all insert information - * @throws EMFUserError - * If an Exception occurred + * @param obj The object containing all insert information + * @throws EMFUserError If an Exception occurred */ @Override public Integer insertBIObject(BIObject obj) throws EMFUserError { @@ -1002,12 +967,9 @@ public Integer insertBIObject(BIObject obj) throws EMFUserError { /** * Implements the query to insert a BIObject. All information needed is stored into the input BIObject object. * - * @param obj - * The object containing all insert information - * @param loadParsDC - * boolean for management Document Composition params - * @throws EMFUserError - * If an Exception occurred + * @param obj The object containing all insert information + * @param loadParsDC boolean for management Document Composition params + * @throws EMFUserError If an Exception occurred */ @Override public void insertBIObject(BIObject obj, boolean loadParsDC) throws EMFUserError { @@ -1017,12 +979,9 @@ public void insertBIObject(BIObject obj, boolean loadParsDC) throws EMFUserError /** * Implements the query to insert a BIObject. All information needed is stored into the input BIObject object. * - * @param obj - * The object containing all insert information - * @param loadParsDC - * boolean for management Document Composition params - * @throws EMFUserError - * If an Exception occurred + * @param obj The object containing all insert information + * @param loadParsDC boolean for management Document Composition params + * @throws EMFUserError If an Exception occurred */ @Override public Integer insertBIObject(BIObject obj, ObjTemplate objTemp) throws EMFUserError { @@ -1032,12 +991,9 @@ public Integer insertBIObject(BIObject obj, ObjTemplate objTemp) throws EMFUserE /** * Implements the query to insert a BIObject. All information needed is stored into the input BIObject object. * - * @param obj - * The object containing all insert information - * @param loadParsDC - * boolean for management Document Composition params - * @throws EMFUserError - * If an Exception occurred + * @param obj The object containing all insert information + * @param loadParsDC boolean for management Document Composition params + * @throws EMFUserError If an Exception occurred */ @Override public Integer insertBIObjectForClone(BIObject obj, ObjTemplate objTemp) throws EMFUserError { @@ -1200,12 +1156,9 @@ private Integer internalInsertBIObject(BIObject obj, ObjTemplate objTemp, boolea /** * Erase bi object. * - * @param obj - * the obj - * @param idFunct - * the id funct - * @throws EMFUserError - * the EMF user error + * @param obj the obj + * @param idFunct the id funct + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#eraseBIObject(it.eng.spagobi.analiticalmodel.document.bo.BIObject, java.lang.Integer) */ @Override @@ -1380,13 +1333,10 @@ public void eraseBIObject(BIObject obj, Integer idFunct) throws EMFUserError { /** * Gets the correct roles for execution. * - * @param id - * the id - * @param profile - * the profile + * @param id the id + * @param profile the profile * @return the correct roles for execution - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#getCorrectRolesForExecution(java.lang.Integer, it.eng.spago.security.IEngUserProfile) */ @Override @@ -1406,11 +1356,9 @@ public List getCorrectRolesForExecution(Integer id, IEngUserProfile profile) thr /** * Gets the correct roles for execution. * - * @param id - * the id + * @param id the id * @return the correct roles for execution - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.analiticalmodel.document.dao.IBIObjectDAO#getCorrectRolesForExecution(java.lang.Integer) */ @Override @@ -1431,13 +1379,10 @@ public List getCorrectRolesForExecution(Integer id) throws EMFUserError { /** * Gets a list of correct role according to the report at input, identified by its id * - * @param id - * The Integer representing report's id - * @param roles - * The collection of all roles + * @param id The Integer representing report's id + * @param roles The collection of all roles * @return The correct roles list - * @throws EMFUserError - * if any exception occurred + * @throws EMFUserError if any exception occurred */ private List getCorrectRoles(Integer id, Collection roles) throws EMFUserError { logger.debug("IN"); @@ -1500,15 +1445,14 @@ private List getCorrectRoles(Integer id, Collection roles) throws EMFUserError { // or TEST state), // it is a correct role String role = rolesIt.next().toString(); - //TESTER management: add all available folders execution roles - String roleTHql = "select roles.roleTypeCode from SbiExtRoles as roles " - + "where roles.name = '" + role + "' "; + // TESTER management: add all available folders execution roles + String roleTHql = "select roles.roleTypeCode from SbiExtRoles as roles " + "where roles.name = '" + role + "' "; Query roleHqlQuery = aSession.createQuery(roleTHql); - String roleType = (String)roleHqlQuery.uniqueResult(); + String roleType = (String) roleHqlQuery.uniqueResult(); if (SpagoBIConstants.ROLE_TYPE_TEST.equals(roleType)) { userRolesWithPermission = allRolesWithPermission; break; - }else { + } else { if (allRolesWithPermission.contains(role)) userRolesWithPermission.add(role); } @@ -1587,8 +1531,7 @@ private List getCorrectRoles(Integer id, Collection roles) throws EMFUserError { /** * From the Hibernate BI object at input, gives the corrispondent BI object. * - * @param hibBIObject - * The Hibernate BI object + * @param hibBIObject The Hibernate BI object * @return the corrispondent output BIObject */ @Override @@ -1750,8 +1693,7 @@ public BIObject toBIObject(SbiObjects hibBIObject, Session session) throws EMFUs /** * From the hibernate BI object parameter at input, gives the corrispondent BIObjectParameter object. * - * @param hiObjPar - * The hybernate BI object parameter + * @param hiObjPar The hybernate BI object parameter * @return The corrispondent BIObjectParameter */ public BIObjectParameter toBIObjectParameter(SbiObjPar hiObjPar) { @@ -2068,11 +2010,9 @@ public List loadPaginatedSearchBIObjects(Integer page, Integer item_co /** * Gets the biparameters associated with to a biobject. * - * @param aBIObject - * BIObject the biobject to analize + * @param aBIObject BIObject the biobject to analize * @return List, list of the biparameters associated with the biobject - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public List getBIObjectParameters(BIObject aBIObject) throws EMFUserError { @@ -2233,14 +2173,10 @@ public BIObject loadBIObjectForDetail(String path) throws EMFUserError { /** * Called only for document composition (update object modality). Puts parameters into the document composition getting these from document's children. * - * @param aSession - * the hibernate session - * @param biObject - * the BI object of document composition - * @param template - * the BI last active template - * @param flgDelete - * the flag that suggest if is necessary to delete parameters before the insertion + * @param aSession the hibernate session + * @param biObject the BI object of document composition + * @param template the BI last active template + * @param flgDelete the flag that suggest if is necessary to delete parameters before the insertion * @throws EMFUserError */ private void insertParametersDocComposition(BIObject biObject, ObjTemplate template, boolean flgDelete) throws EMFUserError { @@ -2356,8 +2292,7 @@ private void insertParametersDocComposition(BIObject biObject, ObjTemplate templ /** * Called only for document composition (insert object modality). Puts parameters into the document composition getting these from document's children. * - * @param biobjectId - * the document composition biobject id + * @param biobjectId the document composition biobject id * @throws EMFUserError */ private void insertParametersDocComposition(Integer biobjectId) throws EMFUserError { @@ -2531,8 +2466,7 @@ public List loadBIObjects(String type, String state, String folderPath) throws E * Loads visible objects of the user roles * * @param folderID - * @param profile - * the profile of the user + * @param profile the profile of the user * @return * @throws EMFUserError */ @@ -2756,7 +2690,7 @@ public List loadAllBIObjectsBySearchKey(String searchKey, String attri while (it.hasNext()) { SbiObjects next = (SbiObjects) it.next(); Integer id = next.getBiobjId(); - if(!resultIds.contains(id)) { + if (!resultIds.contains(id)) { resultIds.add(id); result.add(toBIObject(next, aSession)); } @@ -2781,16 +2715,11 @@ public List loadAllBIObjectsBySearchKey(String searchKey, String attri /** * Search objects with the features specified * - * @param valueFilter - * the value of the filter for the research - * @param typeFilter - * the type of the filter (the operator: equals, starts...) - * @param columnFilter - * the column on which the filter is applied - * @param nodeFilter - * the node (folder id) on which the filter is applied - * @param profile - * the profile of the user + * @param valueFilter the value of the filter for the research + * @param typeFilter the type of the filter (the operator: equals, starts...) + * @param columnFilter the column on which the filter is applied + * @param nodeFilter the node (folder id) on which the filter is applied + * @param profile the profile of the user * @return * @throws EMFUserError */ diff --git a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/IObjTemplateDAO.java b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/IObjTemplateDAO.java index f452978fd54..a577c09dc8b 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/IObjTemplateDAO.java +++ b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/IObjTemplateDAO.java @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -27,6 +27,7 @@ import it.eng.spago.error.EMFUserError; import it.eng.spagobi.analiticalmodel.document.bo.BIObject; import it.eng.spagobi.analiticalmodel.document.bo.ObjTemplate; +import it.eng.spagobi.analiticalmodel.document.metadata.SbiObjTemplates; import it.eng.spagobi.commons.dao.ISpagoBIDao; public interface IObjTemplateDAO extends ISpagoBIDao { @@ -34,78 +35,66 @@ public interface IObjTemplateDAO extends ISpagoBIDao { /** * Gets the bI object active template. * - * @param biobjId - * the biobj id + * @param biobjId the biobj id * * @return the bI object active template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public ObjTemplate getBIObjectActiveTemplate(Integer biobjId) throws EMFInternalError; /** * Gets the bI object active template starting by document label * - * @param biobjLabel - * the BiObject label + * @param biobjLabel the BiObject label * * @return the bI object active template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public ObjTemplate getBIObjectActiveTemplateByLabel(String label) throws EMFInternalError; /** * Gets the bI object template list. * - * @param biobjId - * the biobj id + * @param biobjId the biobj id * * @return the bI object template list * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public List getBIObjectTemplateList(Integer biobjId) throws EMFInternalError; /** * Gets the bI object template list. * - * @param biobjLabel - * the biobj label + * @param biobjLabel the biobj label * * @return the bI object template list * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ - //public List getBIObjectTemplateListByDocLabel(String biobjLabel) throws EMFInternalError; + // public List getBIObjectTemplateListByDocLabel(String biobjLabel) throws EMFInternalError; /** * Load bi object template. * - * @param tempId - * the temp id + * @param tempId the temp id * * @return the obj template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public ObjTemplate loadBIObjectTemplate(Integer tempId) throws EMFInternalError; /** * Gets the next prog for template. * - * @param biobjId - * the biobj id + * @param biobjId the biobj id * * @return the next prog for template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public List getAllTemplateWithoutActive(String data) throws EMFInternalError, ParseException; @@ -116,47 +105,40 @@ public interface IObjTemplateDAO extends ISpagoBIDao { /** * Delete bi object template. * - * @param tempId - * the temp id + * @param tempId the temp id * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public void deleteBIObjectTemplate(Integer tempId) throws EMFInternalError; /** * Setting active bi object template. * - * @param objTemplate - * the new template + * @param objTemplate the new template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public void setTemplateActive(ObjTemplate objTemplate, BIObject biObject) throws EMFUserError, EMFInternalError; /** * Insert a new bi object template. * - * @param objTemplate - * the new template + * @param objTemplate the new template * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public void insertBIObjectTemplate(ObjTemplate objTemplate, BIObject biObject); /** * Change activity of doc's template. * - * @param biObjId - * biobj id - * @param tempId - * temp id + * @param biObjId biobj id + * @param tempId temp id * - * @throws EMFInternalError - * the EMF internal error + * @throws EMFInternalError the EMF internal error */ public void setPreviousTemplateActive(Integer biObjId, Integer tempId) throws EMFInternalError; + public ObjTemplate toObjTemplate(SbiObjTemplates hibObjTemp); + } diff --git a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/ObjTemplateDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/ObjTemplateDAOHibImpl.java index bfd41cc353c..4ec2c301062 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/ObjTemplateDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/analiticalmodel/document/dao/ObjTemplateDAOHibImpl.java @@ -352,14 +352,15 @@ public Integer getNextProgForTemplate(Integer biobjId) throws EMFInternalError { /** * To obj template. * - * @param hibObjTemp - * the hib obj temp + * @param hibObjTemp the hib obj temp * @return the obj template */ + @Override public ObjTemplate toObjTemplate(SbiObjTemplates hibObjTemp) { ObjTemplate objTemp = new ObjTemplate(); objTemp.setActive(hibObjTemp.getActive()); objTemp.setBinId(hibObjTemp.getSbiBinContents().getId()); + objTemp.setContent(hibObjTemp.getSbiBinContents().getContent()); objTemp.setBiobjId(hibObjTemp.getSbiObject().getBiobjId()); objTemp.setCreationDate(hibObjTemp.getCreationDate()); objTemp.setId(hibObjTemp.getObjTempId()); diff --git a/knowagedao/src/main/java/it/eng/spagobi/behaviouralmodel/lov/bo/QueryDetail.java b/knowagedao/src/main/java/it/eng/spagobi/behaviouralmodel/lov/bo/QueryDetail.java index 88a246a06fe..01e2175ebc8 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/behaviouralmodel/lov/bo/QueryDetail.java +++ b/knowagedao/src/main/java/it/eng/spagobi/behaviouralmodel/lov/bo/QueryDetail.java @@ -334,14 +334,27 @@ public String getWrappedStatement(List dependencies, L String result = getQueryDefinition(); if (dependencies != null && dependencies.size() > 0 && drivers != null) { StringBuffer buffer = new StringBuffer(); - buffer.append("SELECT * FROM (" + getQueryDefinition() + ") LovTableForCache "); - buildWhereClause(buffer, dependencies, drivers); + if (result.contains("order by")) { + int index = result.indexOf("order"); + String queryWithoutOrderBy = result.substring(0, index - 1); + buffer.append("SELECT * FROM (" + queryWithoutOrderBy + ") LovTableForCache "); + buildWhereClause(buffer, dependencies, drivers); + buildOrderByClause(buffer, result, index); + } else { + buffer.append("SELECT * FROM (" + getQueryDefinition() + ") LovTableForCache "); + buildWhereClause(buffer, dependencies, drivers); + } result = buffer.toString(); } logger.debug("OUT.result=" + result); return result; } + private void buildOrderByClause(StringBuffer buffer, String result, int index) { + String orderByClause = result.substring(index); + buffer.append(orderByClause); + } + private String getRandomAlias() { return StringUtilities.getRandomString(8); } @@ -381,7 +394,7 @@ private void buildWhereClause(StringBuffer buffer, List loadAllConfigParameters() throws Exception { /** * Load configuration by id. * - * @param id - * the configuration id + * @param id the configuration id * * @return the config object * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.common.bo.dao.ISbiConfigDAO#loadConfigParametersById(integer) */ @@ -141,13 +139,11 @@ public Config loadConfigParametersById(int id) throws Exception { /** * Load configuration by complete label. * - * @param label - * the configuration label + * @param label the configuration label * * @return the config object * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.common.bo.dao.ISbiConfigDAO#loadConfigParametersById(string) */ @@ -188,13 +184,11 @@ public Config loadConfigParametersByLabel(String label) throws Exception { /** * Load configuration by a property node. * - * @param prop - * the configuration label + * @param prop the configuration label * * @return a list with all children of the property node * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.common.bo.dao.ISbiConfigDAO#loadConfigParametersByProperties(string) */ @@ -229,13 +223,11 @@ public SbiConfig fromConfig(Config config) { /** * Save config by id. * - * @param id - * the id + * @param id the id * * @return void * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * */ @Override @@ -297,20 +289,18 @@ public void saveConfig(Config config) throws EMFUserError { aSession.close(); } } - SingletonConfig.getInstance().clearCache(); + ConfigurationCache.getCache().clear(); logger.debug("OUT"); } /** * Delete config by id. * - * @param id - * the id + * @param id the id * * @return void * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * */ @Override @@ -345,7 +335,6 @@ public void delete(Integer idConfig) throws EMFUserError { sess.close(); } } - SingletonConfig.getInstance().clearCache(); logger.debug("OUT"); } diff --git a/knowagedao/src/main/java/it/eng/spagobi/commons/dao/RoleDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/commons/dao/RoleDAOHibImpl.java index faba97d4a06..156d26aca23 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/commons/dao/RoleDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/commons/dao/RoleDAOHibImpl.java @@ -77,9 +77,11 @@ public class RoleDAOHibImpl extends AbstractHibernateDAO implements IRoleDAO { /** * Load by id. * - * @param roleID the role id + * @param roleID + * the role id * @return the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#loadByID(java.lang.Integer) */ @Override @@ -151,9 +153,11 @@ public SbiExtRoles loadSbiExtRoleById(Integer roleId) throws EMFUserError { /** * Load by name. * - * @param roleName the role name + * @param roleName + * the role name * @return the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#loadByName(java.lang.String) */ @Override @@ -208,7 +212,8 @@ public SbiExtRoles loadByNameInSession(String roleName, Session aSession) { * Load all roles. * * @return the list - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#loadAllRoles() */ @Override @@ -335,8 +340,10 @@ public List loadRolesItem(JSONObject item) throws EMFUserError, JSONException { /** * Insert role. * - * @param aRole the a role - * @throws EMFUserError the EMF user error + * @param aRole + * the a role + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#insertRole(it.eng.spagobi.commons.bo.Role) */ @Override @@ -393,8 +400,10 @@ public void insertRoleWithSession(Role aRole, Session aSession) { /** * Erase role. * - * @param aRole the a role - * @throws EMFUserError the EMF user error + * @param aRole + * the a role + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#eraseRole(it.eng.spagobi.commons.bo.Role) */ @Override @@ -475,8 +484,10 @@ public void unsetOtherPublicRole(Session aSession) { /** * Modify role. * - * @param aRole the a role - * @throws EMFUserError the EMF user error + * @param aRole + * the a role + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#modifyRole(it.eng.spagobi.commons.bo.Role) */ @Override @@ -622,15 +633,18 @@ private boolean isAbleTo(Role aRole, SbiAuthorizations authI) { || (authI.getName().equals("CREATE_SELF_SERVICE_COCKPIT") && aRole.isAbleToCreateSelfServiceCockpit()) || (authI.getName().equals("CREATE_SELF_SERVICE_KPI") && aRole.isAbleToCreateSelfServiceKpi()) || (authI.getName().equals("CREATE_SELF_SERVICE_GEOREPORT") && aRole.isAbleToCreateSelfServiceGeoreport()) - || (authI.getName().equals("EDIT_PYTHON_SCRIPTS") && aRole.isAbleToEditPythonScripts()); + || (authI.getName().equals("EDIT_PYTHON_SCRIPTS") && aRole.isAbleToEditPythonScripts()) + || (authI.getName().equals("CREATE_CUSTOM_CHART") && aRole.isAbleToCreateCustomChart()); } /** * Load all free roles for insert. * - * @param parameterID the parameter id + * @param parameterID + * the parameter id * @return the list - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#loadAllFreeRolesForInsert(java.lang.Integer) */ @Override @@ -693,9 +707,11 @@ public List loadAllFreeRolesForInsert(Integer parameterID) throws EMFUserError { /** * Load all free roles for detail. * - * @param parUseID the par use id + * @param parUseID + * the par use id * @return the list - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error * @see it.eng.spagobi.commons.dao.IRoleDAO#loadAllFreeRolesForDetail(java.lang.Integer) */ @Override @@ -773,9 +789,9 @@ public Role toBasicRole(SbiExtRoles hibExtRole) { role.setName(hibExtRole.getName()); role.setDescription(hibExtRole.getDescr()); // role.setCode(hibExtRole.getCode()); -// role.setRoleTypeCD(hibExtRole.getRoleTypeCode()); -// role.setRoleTypeID(hibExtRole.getRoleType().getValueId()); -// role.setOrganization(hibExtRole.getCommonInfo().getOrganization()); + // role.setRoleTypeCD(hibExtRole.getRoleTypeCode()); + // role.setRoleTypeID(hibExtRole.getRoleType().getValueId()); + // role.setOrganization(hibExtRole.getCommonInfo().getOrganization()); logger.debug("OUT"); return role; @@ -784,7 +800,8 @@ public Role toBasicRole(SbiExtRoles hibExtRole) { /** * From the hibernate Role at input, gives the corrispondent Role object. * - * @param hibRole The hybernate role + * @param hibRole + * The hybernate role * @return The corrispondent Role object */ public Role toRole(SbiExtRoles hibRole) { @@ -806,6 +823,9 @@ public Role toRole(SbiExtRoles hibRole) { if (name.equals("EDIT_PYTHON_SCRIPTS")) { role.setIsAbleToEditPythonScripts(true); } + if (name.equals("CREATE_CUSTOM_CHART")) { + role.setIsAbleToCreateCustomChart(true); + } if (name.equals("SAVE_SUBOBJECTS")) { role.setIsAbleToSaveSubobjects(true); } @@ -942,9 +962,11 @@ public Role toRole(SbiExtRoles hibRole) { /** * Gets all the authorizations associated to the role. * - * @param roleID The role id + * @param roleID + * The role id * @return The authorizations associated to the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List LoadFunctionalitiesAssociated(Integer roleID) throws EMFUserError { @@ -983,9 +1005,11 @@ public List LoadFunctionalitiesAssociated(Integer roleID) throws EMFUserError { /** * Gets all the parameter uses associated to the role. * - * @param roleID The role id + * @param roleID + * The role id * @return The parameter uses associated to the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List LoadParUsesAssociated(Integer roleID) throws EMFUserError { @@ -1522,7 +1546,8 @@ public void removeRoleDataSetCategory(Integer roleId, Integer categoryId) throws * Gets all the Authorizationsations present * * @return The authorizations - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List loadAllAuthorizations() throws EMFUserError { @@ -1558,7 +1583,8 @@ public List loadAllAuthorizations() throws EMFUserError { * Gets all the Authorizations for product Types * * @return The authorizations - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List loadAllAuthorizationsByProductTypes(List productTypesIds) throws EMFUserError { @@ -1595,7 +1621,8 @@ public List loadAllAuthorizationsByProductTypes(List * Gets all the Authorizations names for product Types * * @return The authorizations - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List loadAllAuthorizationsNamesByProductTypes(List productTypesIds) throws EMFUserError { @@ -1631,9 +1658,11 @@ public List loadAllAuthorizationsNamesByProductTypes(List produ /** * Gets all the authorizations associated to the role. * - * @param roleID The role id + * @param roleID + * The role id * @return The authorizations associated to the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List LoadAuthorizationsAssociatedToRole(Integer roleID) throws EMFUserError { @@ -1670,9 +1699,11 @@ public List LoadAuthorizationsAssociatedToRole(Integer roleID /** * Gets all the authorizationsRoles object (relationn objects) associated to the role. * - * @param roleID The role id + * @param roleID + * The role id * @return The authorizations associated to the role - * @throws EMFUserError the EMF user error + * @throws EMFUserError + * the EMF user error */ @Override public List LoadAuthorizationsRolesAssociatedToRole(Integer roleID) throws EMFUserError { diff --git a/knowagedao/src/main/java/it/eng/spagobi/commons/dao/TenantsDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/commons/dao/TenantsDAOHibImpl.java index 95d1ee38ae8..d432caecf52 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/commons/dao/TenantsDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/commons/dao/TenantsDAOHibImpl.java @@ -480,6 +480,7 @@ private void setDefaultAuthorizationsForAdmin(Role aRole) { aRole.setIsAbleToSaveMetadata(true); aRole.setIsAbleToSaveRememberMe(true); aRole.setIsAbleToEditPythonScripts(true); + aRole.setIsAbleToCreateCustomChart(true); aRole.setIsAbleToSaveSubobjects(true); aRole.setIsAbleToSeeDocumentBrowser(true); aRole.setIsAbleToSeeFavourites(true); @@ -784,9 +785,12 @@ private void checkAuthorizationsRoles(SbiTenant aTenant, ArrayList> oldAuthMap, SbiTenant aTenant, ArrayList productTypesIds) { @@ -933,7 +937,8 @@ public void deleteTenant(SbiTenant aTenant) throws EMFUserError { * When modifying a tenant if a datasource remains with no tenant delete it * * @param aSession - * @param ids: id of modified + * @param ids: + * id of modified * @throws EMFUserError */ diff --git a/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/HibernateSessionManager.java b/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/HibernateSessionManager.java index 14d885487cf..62597de1498 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/HibernateSessionManager.java +++ b/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/HibernateSessionManager.java @@ -79,6 +79,13 @@ public class HibernateSessionManager { private static void initSessionFactory() { logger.info("Initializing hibernate Session Factory Described by [" + DAOConfig.getHibernateConfigurationFile() + "]"); + Configuration conf = setDialectPropertyToConfiguration(); + + sessionFactory = conf.buildSessionFactory(); + + } + + private static Configuration setDialectPropertyToConfiguration() { Configuration conf = new Configuration(); File hibernateConfigurationFileFile = DAOConfig.getHibernateConfigurationFileFile(); if (hibernateConfigurationFileFile != null) { @@ -96,8 +103,15 @@ private static void initSessionFactory() { logger.warn("Property hibernate.dialect not set! Trying to figure out what dialect needs to be used..."); determineDialect(conf); } + return conf; + } - sessionFactory = conf.buildSessionFactory(); + public static String getDialect() { + logger.info("Initializing hibernate Session Factory Described by [" + DAOConfig.getHibernateConfigurationFile() + "]"); + + Configuration conf = setDialectPropertyToConfiguration(); + + return conf.getProperty(PROPERTY_DIALECT); } /** @@ -106,13 +120,33 @@ private static void initSessionFactory() { * @param conf Actual Hibernate configuration */ private static void determineDialect(Configuration conf) { - String figuredOutValue; String datasourceJndi = conf.getProperty(PROPERTY_DATASOURCE_JNDI); if (datasourceJndi == null) { throw new IllegalStateException("The property hibernate.connection.datasource is not set in file"); } + String figuredOutValue = getDialect(datasourceJndi); + logger.warn("Property hibernate.dialect set to " + figuredOutValue); + conf.setProperty(PROPERTY_DIALECT, figuredOutValue); + + } + + public static String determineDialectFromJNDIResource(String datasourceJndi) { + + if (datasourceJndi == null) { + throw new IllegalStateException("The property hibernate.connection.datasource is not set in file"); + } + + String figuredOutValue = getDialect(datasourceJndi); + logger.warn("Property hibernate.dialect set to " + figuredOutValue); + + return figuredOutValue; + } + + private static String getDialect(String datasourceJndi) { + String figuredOutValue = null; + Connection connection = null; try { InitialContext ctx = new InitialContext(); @@ -131,10 +165,6 @@ private static void determineDialect(Configuration conf) { } figuredOutValue = JDBC_URL_PREFIX_2_DIALECT.get(urlPrefix); - - logger.warn("Property hibernate.dialect set to " + figuredOutValue); - conf.setProperty(PROPERTY_DIALECT, figuredOutValue); - } catch (Exception e) { logger.error("Error determining Hibernate's dialect", e); } finally { @@ -146,6 +176,8 @@ private static void determineDialect(Configuration conf) { } } } + return figuredOutValue; + } private synchronized static SessionFactory getSessionFactory() { diff --git a/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/UserUtilities.java b/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/UserUtilities.java index ebd359aff26..8ff570adb8c 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/UserUtilities.java +++ b/knowagedao/src/main/java/it/eng/spagobi/commons/utilities/UserUtilities.java @@ -17,6 +17,8 @@ */ package it.eng.spagobi.commons.utilities; +import static it.eng.spagobi.commons.constants.SpagoBIConstants.DOCUMENT_WIDGET_USE; + import java.io.IOException; import java.lang.reflect.Method; import java.security.Principal; @@ -118,7 +120,8 @@ public static String getSchema(String ente, IEngUserProfile userProfile) { * Gets the user profile. * * @return the user profile - * @throws Exception the exception + * @throws Exception + * the exception */ public static IEngUserProfile getUserProfile() throws Exception { RequestContainer aRequestContainer = RequestContainer.getRequestContainer(); @@ -425,9 +428,11 @@ public static boolean haveRoleAndAuthorization(IEngUserProfile profile, String R /** * User functionality root exists. * - * @param username the username + * @param username + * the username * @return true, if successful - * @throws Exception the exception + * @throws Exception + * the exception */ public static boolean userFunctionalityRootExists(String username) throws Exception { boolean exists = false; @@ -445,9 +450,11 @@ public static boolean userFunctionalityRootExists(String username) throws Except /** * User functionality root exists. * - * @param userProfile the user profile + * @param userProfile + * the user profile * @return true, if successful - * @throws Exception the exception + * @throws Exception + * the exception */ public static boolean userFunctionalityRootExists(UserProfile userProfile) { Assert.assertNotNull(userProfile, "User profile in input is null"); @@ -465,8 +472,10 @@ public static boolean userFunctionalityRootExists(UserProfile userProfile) { * Load the user personal folder as a LowFunctionality object. If the personal folder exists, it is returned; if it does not exist and create is false, null * is returned, otherwise the personal folder is created and then returned. * - * @param userProfile UserProfile the user profile object - * @param createIfNotExisting Boolean that specifies if the personal folder must be created if it doesn't exist + * @param userProfile + * UserProfile the user profile object + * @param createIfNotExisting + * Boolean that specifies if the personal folder must be created if it doesn't exist * @return the personal folder as a LowFunctionality object, or null in case the personal folder does not exist and create is false */ public static LowFunctionality loadUserFunctionalityRoot(UserProfile userProfile, boolean createIfNotExisting) { @@ -523,8 +532,10 @@ public static boolean isAPersonalFolder(LowFunctionality folder) { /** * Creates the user functionality root. * - * @param userProfile the user profile - * @throws Exception the exception + * @param userProfile + * the user profile + * @throws Exception + * the exception */ public static void createUserFunctionalityRoot(IEngUserProfile userProfile) throws Exception { logger.debug("IN"); @@ -743,7 +754,9 @@ public static List readFunctionalityByRole(SpagoBIUserProfile user) { if (virtualRole.isAbleToEditPythonScripts()) { roleFunctionalities.add(SpagoBIConstants.EDIT_PYTHON_SCRIPTS); } - + if (virtualRole.isAbleToCreateCustomChart()) { + roleFunctionalities.add(SpagoBIConstants.CREATE_CUSTOM_CHART); + } if (!roleFunctionalities.isEmpty()) { List roleTypeFunctionalities = Arrays.asList(functionalities); roleFunctionalities.addAll(roleTypeFunctionalities); @@ -785,11 +798,25 @@ public static List readFunctionalityByLicense(SpagoBIUserProfile user) { } } catch (Exception e) { logger.debug("Server Manager not installed or not installer correctly.", e); + licenseFunctionalities.addAll(freeFunctionalities()); + logger.debug("Add following free functionalities: " + licenseFunctionalities, e); } logger.debug("OUT"); return licenseFunctionalities; } + /** + * Add commons functionalities availables only in the Enterprise to the Community for free. + * + * @return List of functionalities + */ + private static List freeFunctionalities() { + List ret = new ArrayList<>(); + ret.add(DOCUMENT_WIDGET_USE); + ret.add("MapWidgetUse"); + return ret; + } + public static String getUserId(HttpServletRequest req) { logger.debug("IN"); SsoServiceInterface userProxy = SsoServiceFactory.createProxyService(); @@ -814,6 +841,10 @@ private static Role getVirtualRole(String[] roles, String organization) throws E logger.debug("User has role " + roleName + " that is able to edit python scripts."); virtualRole.setIsAbleToEditPythonScripts(true); } + if (anotherRole.isAbleToCreateCustomChart()) { + logger.debug("User has role " + roleName + " that is able to create custom chart."); + virtualRole.setIsAbleToCreateCustomChart(true); + } if (anotherRole.isAbleToSaveSubobjects()) { logger.debug("User has role " + roleName + " that is able to save subobjects."); virtualRole.setIsAbleToSaveSubobjects(true); @@ -1042,7 +1073,8 @@ public static ISecurityServiceSupplier createISecurityServiceSupplier() { * Clones the input profile object. We don't implement the SpagoBIUserProfile.clone method because SpagoBIUserProfile is created by Axis tools, and * therefore, when generating the class we may lost that method. * - * @param profile The input SpagoBIUserProfile object + * @param profile + * The input SpagoBIUserProfile object * @return a clone of the input SpagoBIUserProfile object */ public static SpagoBIUserProfile clone(SpagoBIUserProfile profile) { diff --git a/knowagedao/src/main/java/it/eng/spagobi/community/util/CommunityUtilities.java b/knowagedao/src/main/java/it/eng/spagobi/community/util/CommunityUtilities.java index c14da1acc11..89b3ce79f66 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/community/util/CommunityUtilities.java +++ b/knowagedao/src/main/java/it/eng/spagobi/community/util/CommunityUtilities.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,20 +11,32 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.community.util; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.mail.Message; +import javax.mail.internet.InternetAddress; +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; + +import it.eng.knowage.mail.MailSessionBuilder; +import it.eng.knowage.mail.MailSessionBuilder.SessionFacade; import it.eng.spago.base.RequestContainer; import it.eng.spago.base.RequestContainerAccess; import it.eng.spago.base.SessionContainer; -import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.commons.constants.SpagoBIConstants; import it.eng.spagobi.commons.dao.DAOFactory; import it.eng.spagobi.commons.utilities.ChannelUtilities; -import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.commons.utilities.messages.IMessageBuilder; import it.eng.spagobi.commons.utilities.messages.MessageBuilderFactory; import it.eng.spagobi.profiling.bean.SbiUser; @@ -32,50 +44,29 @@ import it.eng.spagobi.utilities.exceptions.SpagoBIServiceException; import it.eng.spagobi.utilities.themes.ThemesManager; -import java.security.Security; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Properties; -import java.util.Set; - -import javax.mail.Authenticator; -import javax.mail.Message; -import javax.mail.PasswordAuthentication; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeMessage; -import javax.servlet.http.HttpServletRequest; - -import org.apache.log4j.Logger; - public class CommunityUtilities { static private Logger logger = Logger.getLogger(CommunityUtilities.class); - final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; - final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; - + public boolean dispatchMail(String communityName, SbiUser userToAccept, SbiUser owner, String ownerEmail, HttpServletRequest request) { Locale locale = null; RequestContainer reqCont = RequestContainerAccess.getRequestContainer(request); if(reqCont != null){ SessionContainer aSessionContainer = reqCont.getSessionContainer(); - + SessionContainer permanentSession = aSessionContainer.getPermanentContainer(); String curr_language=(String)permanentSession.getAttribute(SpagoBIConstants.AF_LANGUAGE); String curr_country=(String)permanentSession.getAttribute(SpagoBIConstants.AF_COUNTRY); - + if(curr_language!=null && curr_country!=null && !curr_language.equals("") && !curr_country.equals("")){ locale=new Locale(curr_language, curr_country, ""); } } - String currTheme=ThemesManager.getDefaultTheme(); + String currTheme=ThemesManager.getDefaultTheme(); logger.debug("currTheme: "+currTheme); - + IMessageBuilder msgBuilder = MessageBuilderFactory.getMessageBuilder(); - // get message + // get message String msg1 = msgBuilder.getMessage("community.accept.mail.1", "messages", request); String msg2 = msgBuilder.getMessage("community.accept.mail.2", "messages", request); String msg3 = msgBuilder.getMessage("community.accept.mail.3", "messages", request); @@ -83,13 +74,13 @@ public boolean dispatchMail(String communityName, SbiUser userToAccept, SbiUser String msg3_2 = msgBuilder.getMessage("community.accept.mail.3.2", "messages", request); String msg3_3 = msgBuilder.getMessage("community.accept.mail.3.3", "messages", request); String msg3_4 = msgBuilder.getMessage("community.accept.mail.3.4", "messages", request); - String msg3_5 = msgBuilder.getMessage("community.accept.mail.3.5", "messages", request); + String msg3_5 = msgBuilder.getMessage("community.accept.mail.3.5", "messages", request); String msg4 = msgBuilder.getMessage("community.accept.mail.4", "messages", request); String msg5 = msgBuilder.getMessage("community.accept.mail.5", "messages", request); - String msgwarn = msgBuilder.getMessage("community.accept.mail.warn", "messages", request); - + String msgwarn = msgBuilder.getMessage("community.accept.mail.warn", "messages", request); + String contextName = ChannelUtilities.getSpagoBIContextName(request); - + String mailSubj = "Community "+communityName+" membership request"; StringBuffer sb = new StringBuffer(); sb.append(""); @@ -98,11 +89,11 @@ public boolean dispatchMail(String communityName, SbiUser userToAccept, SbiUser sb.append(""); sb.append(""); sb.append("

"); - + sb.append(msg1+"  "+ owner.getFullName()+",
"+msg2+" "+userToAccept.getFullName()+ " "+msg3+" "+communityName+" community."); sb.append("

" + msg3_1 + "

"); - - try{ + + try{ SbiUser userForAttr = DAOFactory.getSbiUserDAO().loadSbiUserById(userToAccept.getId()); Set userAttributes = userForAttr.getSbiUserAttributeses(); List lstAttrs = new ArrayList(); @@ -111,26 +102,26 @@ public boolean dispatchMail(String communityName, SbiUser userToAccept, SbiUser lstAttrs.add("birth_date"); lstAttrs.add("location"); - Iterator itAttrs = userAttributes.iterator(); + Iterator itAttrs = userAttributes.iterator(); while(itAttrs.hasNext()){ SbiUserAttributes userAttr = (SbiUserAttributes)itAttrs.next(); String attrName= userAttr.getSbiAttribute().getAttributeName(); - if (lstAttrs.contains(attrName) && userAttr.getAttributeValue() != null && + if (lstAttrs.contains(attrName) && userAttr.getAttributeValue() != null && userAttr.getAttributeValue() != ""){ sb.append("- " + attrName + ": "+ userAttr.getAttributeValue()+"
"); - } + } } }catch (Throwable t) { throw new SpagoBIServiceException( "An unexpected error occured while executing the subscribe action", t); } sb.append("
"+msg3_5 + "
"); - sb.append("
"+msg4+" "+userToAccept.getFullName()+" "+msg5); + sb.append("
"+msg4+" "+userToAccept.getFullName()+" "+msg5); String schema = request.getScheme(); String server= request.getServerName(); String port= request.getServerPort()+""; - - + + sb.append("
> sbiUserAttributeses = new HashMap>(); @@ -164,4 +166,20 @@ public void setDefaultRoleId(Integer defaultRoleId) { this.defaultRoleId = defaultRoleId; } + public Integer getFailedLoginAttempts() { + return failedLoginAttempts; + } + + public void setFailedLoginAttempts(Integer failedLoginAttempts) { + this.failedLoginAttempts = failedLoginAttempts; + } + + public boolean getBlockedByFailedLoginAttempts() { + return blockedByFailedLoginAttempts; + } + + public void setBlockedByFailedLoginAttempts(boolean blockedByFailedLoginAttempts) { + this.blockedByFailedLoginAttempts = blockedByFailedLoginAttempts; + } + } diff --git a/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiAttributeDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiAttributeDAOHibImpl.java index 05cc9fc9e3e..7ec5ee209e9 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiAttributeDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiAttributeDAOHibImpl.java @@ -22,6 +22,7 @@ import org.apache.log4j.Logger; import org.hibernate.Criteria; +import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; @@ -280,6 +281,7 @@ public SbiAttribute loadSbiAttributeById(Integer id) throws EMFUserError { aSession = getSession(); tx = aSession.beginTransaction(); toReturn = (SbiAttribute) aSession.load(SbiAttribute.class, id); + Hibernate.initialize(toReturn); tx.commit(); } catch (HibernateException he) { logger.error(he.getMessage(), he); diff --git a/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiUserDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiUserDAOHibImpl.java index b22f90b47ac..837e24f1755 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiUserDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/profiling/dao/SbiUserDAOHibImpl.java @@ -41,7 +41,10 @@ import it.eng.qbe.statement.hibernate.HQLStatement; import it.eng.qbe.statement.hibernate.HQLStatement.IConditionalOperator; import it.eng.spago.error.EMFUserError; +import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.commons.dao.AbstractHibernateDAO; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; import it.eng.spagobi.commons.dao.SpagoBIDAOException; import it.eng.spagobi.commons.metadata.SbiExtRoles; import it.eng.spagobi.dao.PagedList; @@ -96,7 +99,7 @@ public SbiUser loadSbiUserById(Integer id) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while loading user by id" + id, he); + throw new SpagoBIDAOException("Error while loading user by id " + id, he); } finally { if (aSession != null) { if (aSession.isOpen()) @@ -144,7 +147,7 @@ public List loadUsers(QueryFilters filters, String dateFilter) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while loading users", he); + throw new SpagoBIDAOException("Error while loading users ", he); } finally { logger.debug("OUT"); if (aSession != null) { @@ -220,7 +223,7 @@ public Integer saveSbiUser(SbiUser user) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while inserting user" + user, he); + throw new SpagoBIDAOException("Error while inserting user " + user, he); } finally { if (aSession != null) { if (aSession.isOpen()) @@ -271,7 +274,7 @@ public void updateSbiUserAttributes(SbiUserAttributes attribute) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while update user attribute" + attribute, he); + throw new SpagoBIDAOException("Error while update user attribute " + attribute, he); } finally { if (aSession != null) { if (aSession.isOpen()) @@ -293,7 +296,7 @@ public void updateSbiUserRoles(SbiExtUserRoles role) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while updating user with role" + role, he); + throw new SpagoBIDAOException("Error while updating user with role " + role, he); } finally { if (aSession != null) { if (aSession.isOpen()) @@ -309,7 +312,7 @@ public SbiUser loadSbiUserByUserId(String userId) { SbiUser user = getSbiUserByUserId(userId); return user; } catch (HibernateException he) { - throw new SpagoBIDAOException("Error while loading user by id" + userId, he); + throw new SpagoBIDAOException("Error while loading user by id " + userId, he); } finally { logger.debug("OUT"); } @@ -341,7 +344,7 @@ public ArrayList loadSbiUserAttributesById(Integer id) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while loading user attribute with id" + id, he); + throw new SpagoBIDAOException("Error while loading user attribute with id " + id, he); } finally { logger.debug("OUT"); if (aSession != null) { @@ -369,7 +372,7 @@ public ArrayList loadSbiUserRolesById(Integer id) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while loading user role with id" + id, he); + throw new SpagoBIDAOException("Error while loading user role with id " + id, he); } finally { logger.debug("OUT"); if (aSession != null) { @@ -456,7 +459,7 @@ public void deleteSbiUserById(Integer id) { } catch (HibernateException he) { if (tx != null) tx.rollback(); - throw new SpagoBIDAOException("Error while deleting user with id" + id, he); + throw new SpagoBIDAOException("Error while deleting user with id " + id, he); } finally { logger.debug("OUT"); if (aSession != null) { @@ -755,6 +758,20 @@ public UserBO toUserBO(SbiUser sbiUser) { userBO.setIsSuperadmin(sbiUser.getIsSuperadmin()); userBO.setDefaultRoleId(sbiUser.getDefaultRoleId()); + IConfigDAO configsDao = DAOFactory.getSbiConfigDAO(); + configsDao.setUserProfile(getUserProfile()); + + Integer maxFailedLoginAttempts = null; + try { + maxFailedLoginAttempts = Integer.valueOf(SingletonConfig.getInstance().getConfigValue("internal.security.login.maxFailedLoginAttempts")); + } catch (NumberFormatException e) { + throw new SpagoBIRuntimeException("Error while retrieving maxFailedLoginAttempts for user ", e); + } catch (Exception e) { + throw new SpagoBIRuntimeException("Error while retrieving maxFailedLoginAttempts for user ", e); + } + userBO.setFailedLoginAttempts(sbiUser.getFailedLoginAttempts()); + userBO.setBlockedByFailedLoginAttempts(sbiUser.getFailedLoginAttempts() >= maxFailedLoginAttempts); + List userRoles = new ArrayList<>(); Set roles = sbiUser.getSbiExtUserRoleses(); for (Iterator it = roles.iterator(); it.hasNext();) { diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/bo/MetaModel.java b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/bo/MetaModel.java index 533466c9e22..60c6c3a8afd 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/bo/MetaModel.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/bo/MetaModel.java @@ -53,6 +53,8 @@ public class MetaModel implements IDrivableBIResource { @Size(max = 100) private String modelLocker; + private Boolean smartView; + private List biMetaModelParameters = null; @ExtendedAlphanumeric @@ -95,7 +97,8 @@ public Integer getCategory() { } /** - * @param category the category to set + * @param category + * the category to set */ public void setCategory(Integer category) { this.category = category; @@ -133,7 +136,8 @@ public Boolean getModelLocked() { } /** - * @param modelLocked the modelLocked to set + * @param modelLocked + * the modelLocked to set */ public void setModelLocked(Boolean modelLocked) { this.modelLocked = modelLocked; @@ -147,19 +151,38 @@ public String getModelLocker() { } /** - * @param modelLocker the modelLocker to set + * @param modelLocker + * the modelLocker to set */ public void setModelLocker(String modelLocker) { this.modelLocker = modelLocker; } -// public List getBiMetaModelParameters() { -// return biMetaModelParameters; -// } -// -// public void setBiMetaModelParameters(List biMetaModelParameters) { -// this.biMetaModelParameters = biMetaModelParameters; -// } + // public List getBiMetaModelParameters() { + // return biMetaModelParameters; + // } + // + // public void setBiMetaModelParameters(List biMetaModelParameters) { + // this.biMetaModelParameters = biMetaModelParameters; + // } + + /** + * @return the smartView + */ + public Boolean getSmartView() { + if (smartView == null) { + return false; + } + return smartView; + } + + /** + * @param smartView + * the smartView to set + */ + public void setSmartView(Boolean smartView) { + this.smartView = smartView; + } @Override public List getDrivers() { diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/dao/MetaModelsDAOImpl.java b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/dao/MetaModelsDAOImpl.java index a2cd0535af7..ccc3e36ceae 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/dao/MetaModelsDAOImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/dao/MetaModelsDAOImpl.java @@ -563,6 +563,7 @@ public void modifyMetaModel(MetaModel model) { hibModel.setTablePrefixNotLike(model.getTablePrefixNotLike()); hibModel.setModelLocker(model.getModelLocker()); hibModel.setModelLocked(model.getModelLocked()); + hibModel.setSmartView(model.getSmartView()); if (model.getDataSourceLabel() != null && !model.getDataSourceLabel().equals("")) { Criterion aCriterion = Expression.eq("label", model.getDataSourceLabel()); Criteria criteria = session.createCriteria(SbiDataSource.class); @@ -623,6 +624,7 @@ public void insertMetaModel(MetaModel model) { hibModel.setTablePrefixNotLike(model.getTablePrefixNotLike()); hibModel.setModelLocker(model.getModelLocker()); hibModel.setModelLocked(model.getModelLocked()); + hibModel.setSmartView(model.getSmartView()); if (model.getDataSourceLabel() != null && !model.getDataSourceLabel().equals("")) { // Criterion aCriterion = Expression.eq("label", model.getDataSourceLabel()); // Criteria criteria = session.createCriteria(SbiDataSource.class); @@ -755,7 +757,7 @@ public MetaModel toModel(SbiMetaModel hibModel) { } toReturn.setModelLocked(hibModel.getModelLocked()); toReturn.setModelLocker(hibModel.getModelLocker()); - + toReturn.setSmartView(hibModel.getSmartView()); } logger.debug("OUT"); return toReturn; diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/metadata/SbiMetaModel.java b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/metadata/SbiMetaModel.java index 1a9d230c6a8..713715ef9ee 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/metadata/SbiMetaModel.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/catalogue/metadata/SbiMetaModel.java @@ -41,6 +41,8 @@ public class SbiMetaModel extends SbiHibernateModel { private String modelLocker; + private Boolean smartView; + private Set biMetaModelParameters = null; private String tablePrefixLike; @@ -94,7 +96,8 @@ public Integer getCategory() { } /** - * @param category the category to set + * @param category + * the category to set */ public void setCategory(Integer category) { this.category = category; @@ -116,7 +119,8 @@ public Boolean getModelLocked() { } /** - * @param modelLocked the modelLocked to set + * @param modelLocked + * the modelLocked to set */ public void setModelLocked(Boolean modelLocked) { this.modelLocked = modelLocked; @@ -130,12 +134,28 @@ public String getModelLocker() { } /** - * @param modelLocker the modelLocker to set + * @param modelLocker + * the modelLocker to set */ public void setModelLocker(String modelLocker) { this.modelLocker = modelLocker; } + /** + * @return the smartView + */ + public Boolean getSmartView() { + return smartView; + } + + /** + * @param smartView + * the smartView to set + */ + public void setSmartView(Boolean smartView) { + this.smartView = smartView; + } + public Set getSbiMetaModelParameters() { return this.biMetaModelParameters; } diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/BIObjDataSetDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/BIObjDataSetDAOHibImpl.java index 82ba14cfc84..35177b41006 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/BIObjDataSetDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/BIObjDataSetDAOHibImpl.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,38 +11,40 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.dataset.dao; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.hibernate.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; + import it.eng.spago.error.EMFUserError; import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.analiticalmodel.document.bo.ObjTemplate; import it.eng.spagobi.analiticalmodel.document.dao.BIObjectDAOHibImpl; import it.eng.spagobi.analiticalmodel.document.metadata.SbiObjects; import it.eng.spagobi.commons.dao.AbstractHibernateDAO; import it.eng.spagobi.commons.dao.DAOFactory; import it.eng.spagobi.commons.dao.SpagoBIDAOException; +import it.eng.spagobi.engines.drivers.IEngineDriver; import it.eng.spagobi.tools.dataset.bo.BIObjDataSet; import it.eng.spagobi.tools.dataset.bo.IDataSet; import it.eng.spagobi.tools.dataset.metadata.SbiObjDataSet; import it.eng.spagobi.utilities.assertion.Assert; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.hibernate.Query; -import org.hibernate.Session; -import org.hibernate.Transaction; - /** * Defines the Hibernate implementations for all DAO methods, for a BI Object Dataset. - * + * * @author Gavardi */ public class BIObjDataSetDAOHibImpl extends AbstractHibernateDAO implements IBIObjDataSetDAO { @@ -428,4 +430,47 @@ public void updateObjectDetailDataset(Integer objectId, Integer dsId, Session cu logger.debug("IN"); } + @Override + public void insertOrUpdateDatasetDependencies(BIObject biObject, ObjTemplate template, Session session) { + + logger.debug("IN"); + + try { + Assert.assertNotNull(session, "session cannot be null"); + + byte[] documentTemplate = template.getContent(); + String driverName = biObject.getEngine().getDriverName(); + if (driverName != null && !"".equals(driverName)) { + try { + IEngineDriver driver = (IEngineDriver) Class.forName(driverName).newInstance(); + ArrayList datasetsAssociated = driver.getDatasetAssociated(documentTemplate); + if (datasetsAssociated != null && !datasetsAssociated.isEmpty()) { + + DAOFactory.getSbiObjDsDAO().deleteObjDsbyObjId(biObject.getId()); + + for (Iterator iterator = datasetsAssociated.iterator(); iterator.hasNext();) { + String string = (String) iterator.next(); + logger.debug("Dataset associated to biObject with label " + biObject.getLabel() + ": " + string); + } + + IBIObjDataSetDAO biObjDatasetDAO = DAOFactory.getBIObjDataSetDAO(); + biObjDatasetDAO.updateObjectNotDetailDatasets(biObject, datasetsAssociated, session); + } else { + logger.debug("No dataset associated to template"); + } + } catch (Exception e) { + logger.error("Error while inserting dataset dependencies; check template format", e); + throw new RuntimeException("Impossible to add template [" + template.getName() + "] to document [" + template.getBiobjId() + + "]; error while recovering dataset associations; check template format."); + } + } + session.flush(); + } catch (Throwable t) { + throw new SpagoBIDAOException("Error while deleting the objDataset associated with object" + biObject.getId(), t); + } finally { + } + logger.debug("OUT"); + + } + } diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetDAOImpl.java b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetDAOImpl.java index 0dc66a4c5ae..4e4ca59bc57 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetDAOImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetDAOImpl.java @@ -152,11 +152,9 @@ public SbiDataSet copyDataSet(SbiDataSet hibDataSet) { /** * Counts number of BIObj associated. * - * @param dsId - * the ds id + * @param dsId the ds id * @return Integer, number of BIObj associated - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public Integer countBIObjAssociated(Integer dsId) { @@ -192,8 +190,7 @@ public Integer countBIObjAssociated(Integer dsId) { * Counts number of existent DataSets * * @return Integer, number of existent DataSets - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public Integer countDatasets() { @@ -339,8 +336,7 @@ public Integer countDatasetsSearch(String search, List tagIds) { /** * Delete all inactive versions of dataset whose id is equal to datasetId * - * @param datasetId - * the id of the of the dataset whose incative version must be deleted + * @param datasetId the id of the of the dataset whose incative version must be deleted * @return true if the incative versions of dataset whose id is equal to datasetId have been succesfully deleted from database. false otherwise * (i.e. the dtaset does not have any inactive versions) */ @@ -406,10 +402,8 @@ public boolean deleteAllInactiveDataSetVersions(Integer datasetId) { /** * Delete data set whose ID is equal to datasetId if it is not referenced by some analytical documents. * - * @param datasetId - * the ID of the dataset to delete. Cannot be null. - * @throws SpagoBIDAOException - * if the dataset is referenced by at least one analytical document + * @param datasetId the ID of the dataset to delete. Cannot be null. + * @throws SpagoBIDAOException if the dataset is referenced by at least one analytical document */ @Override public void deleteDataSet(Integer datasetId) { @@ -554,8 +548,7 @@ public void deleteDataSet(Integer datasetId) { /** * Delete data set whose ID is equal to datasetId ALSO if is referenced by some analytical documents. * - * @param datasetId - * the ID of the dataset to delete. Cannot be null. + * @param datasetId the ID of the dataset to delete. Cannot be null. */ @Override public void deleteDataSetNoChecks(Integer datasetId) { @@ -613,8 +606,7 @@ public void deleteDataSetNoChecks(Integer datasetId) { /** * Delete the dataset version whose id is equal to datasetVersionId if and only if it is inactive. * - * @param datasetVersionId - * the id of the version of the dataset to delete. Cannot be null. + * @param datasetVersionId the id of the version of the dataset to delete. Cannot be null. * @return true if the version whose id is equal to datasetVersionId is deleted from database. false otherwise (the version does not exist or * it exists but it is active). */ @@ -676,10 +668,8 @@ public boolean deleteInactiveDataSetVersion(Integer datasetVersionNum, Integer d /** * Returns the Higher Version Number of a selected DS * - * @param dsId - * the a data set ID - * @throws EMFUserError - * the EMF user error + * @param dsId the a data set ID + * @throws EMFUserError the EMF user error */ @Override public Integer getHigherVersionNumForDS(Integer dsId) { @@ -712,11 +702,9 @@ public Integer getHigherVersionNumForDS(Integer dsId) { /** * Checks for bi lovs associated. * - * @param dsId - * the ds id + * @param dsId the ds id * @return true, if checks for lovs associated - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.tools.dataSet.dao.IDataSetDAO#hasBIObjAssociated(java.lang.String) */ @Override @@ -757,11 +745,9 @@ public boolean hasBILovAssociated(String dsId) { /** * Checks for bi obj associated. * - * @param dsId - * the ds id + * @param dsId the ds id * @return true, if checks for bi obj associated - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.tools.dataSet.dao.IDataSetDAO#hasBIObjAssociated(java.lang.String) */ // @Override @@ -845,8 +831,7 @@ public Integer insertDataSet(IDataSet dataSet) { /** * Insert data set. * - * @param dataSet - * the a data set + * @param dataSet the a data set * @see it.eng.spagobi.tools.dataset.dao.IDataSetDAO#insertDataSet(it.eng.spagobi.tools.dataset.bo.AbstractDataSet) */ @Override @@ -1359,7 +1344,9 @@ public List loadDatasetsBasicInfoForLov() { try { session = getSession(); toReturn = session.createQuery( - "select new it.eng.spagobi.tools.dataset.bo.DataSetBasicInfo(ds.id.dsId, ds.label, ds.name, ds.description, ds.owner, ds.scope.valueCd) from SbiDataSet ds where ds.active = ? and ds.parameters is null") + "select new it.eng.spagobi.tools.dataset.bo.DataSetBasicInfo(ds.id.dsId, ds.label, ds.name, ds.description, ds.owner, ds.scope.valueCd) " + + " from SbiDataSet ds where ds.active = ? " + + " and (ds.parameters is null or (ds.parameters is not null and ds.parameters like '%%'))") .setBoolean(0, true).list(); } catch (Exception e) { throw new SpagoBIDAOException("An unexpected error occured while loading datasets basic info for LOV", e); @@ -1380,9 +1367,8 @@ public List loadDataSetsByOwner(UserProfile user, Boolean includeOwned } /** - * @param scope - * Sent from DatasetResource
- * Can be: "all", "owned", "enterprise" and "shared", depends on Tab from Workspace/Datasets (MyDataset, Shared, Enterprise, All) + * @param scope Sent from DatasetResource
+ * Can be: "all", "owned", "enterprise" and "shared", depends on Tab from Workspace/Datasets (MyDataset, Shared, Enterprise, All) */ @Override public List loadDatasetsByTags(UserProfile user, List tagIds, String scope) { @@ -1995,13 +1981,10 @@ public List loadNotDerivedUserDataSets(UserProfile user) { /** * Returns List of all existent IDataSets with current active version * - * @param offset - * starting element - * @param fetchSize - * number of elements to retrieve + * @param offset starting element + * @param fetchSize number of elements to retrieve * @return List of all existent IDataSets with current active version - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public List loadPagedDatasetList(Integer offset, Integer fetchSize) { @@ -2135,13 +2118,10 @@ public List loadPagedDatasetList(Integer offset, Integer fetchSize) { /** * Returns List of all existent IDataSets with current active version for the owner * - * @param offset - * starting element - * @param fetchSize - * number of elements to retrieve + * @param offset starting element + * @param fetchSize number of elements to retrieve * @return List of all existent IDataSets with current active version - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public List loadPagedDatasetList(Integer offset, Integer fetchSize, String owner) { @@ -2241,13 +2221,10 @@ public List loadPagedDatasetList(Integer offset, Integer fetchSize, St /** * Returns List of all existent SbiDataSet elements (NO DETAIL, only name, label, descr...). * - * @param offset - * starting element - * @param fetchSize - * number of elements to retrieve + * @param offset starting element + * @param fetchSize number of elements to retrieve * @return List of all existent SbiDataSet - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public List loadPagedSbiDatasetConfigList(Integer offset, Integer fetchSize) { @@ -2340,10 +2317,8 @@ public List loadUserDataSets(String user) { /** * Modify data set. * - * @param aDataSet - * the a data set - * @throws EMFUserError - * the EMF user error + * @param aDataSet the a data set + * @throws EMFUserError the EMF user error * @see it.eng.spagobi.tools.dataset.dao.IDataSetDAO#modifyDataSet(it.eng.spagobi.tools.dataset.bo.AbstractDataSet) */ @Override @@ -2535,7 +2510,8 @@ public void modifyDataSet(IDataSet dataSet, Session optionalDbSession) { * @param type * @return */ - public String getDataSource(String type) { + public String getDataSource(SbiDataSet ds) { + String type = ds.getType(); String dataSource = ""; switch (type) { case DataSetConstants.DS_QUERY: @@ -2548,7 +2524,10 @@ public String getDataSource(String type) { break; case DataSetConstants.DS_FLAT: - dataSource = DataSetConstants.DATA_SOURCE_FLAT; + JSONObject jsonConf = ObjectUtils.toJSONObject(ds.getConfiguration()); + + // Old flat dataset has stored the data source to a different attribute + dataSource = jsonConf.has(DataSetConstants.DATA_SOURCE_FLAT) ? DataSetConstants.DATA_SOURCE_FLAT : DataSetConstants.DATA_SOURCE; break; default: logger.debug("Dataset type is [" + type + "], so no need to update older versions cause Datasource can not be ambiguous."); @@ -2568,8 +2547,9 @@ public void updateOlderVersions(IDataSet dataSet) throws JSONException { while (it.hasNext()) { SbiDataSet ds = it.next(); JSONObject jsonConf = ObjectUtils.toJSONObject(ds.getConfiguration()); - if (!dataSourceLabel.equals(jsonConf.get(getDataSource(ds.getType())))) { - jsonConf.put(getDataSource(ds.getType()), dataSourceLabel); + String dataSourceFieldName = getDataSource(ds); + if (!dataSourceLabel.equals(jsonConf.get(dataSourceFieldName))) { + jsonConf.put(dataSourceFieldName, dataSourceLabel); ds.setConfiguration(JSONUtils.escapeJsonString(jsonConf.toString())); updateDataset(ds, getSession()); } @@ -2579,12 +2559,9 @@ public void updateOlderVersions(IDataSet dataSet) throws JSONException { /** * Restore an Older Version of the dataset * - * @param dsId - * the a data set ID - * @param dsVersion - * the a data set Version - * @throws EMFUserError - * the EMF user error + * @param dsId the a data set ID + * @param dsVersion the a data set Version + * @throws EMFUserError the EMF user error */ @Override public IDataSet restoreOlderDataSetVersion(Integer dsId, Integer dsVersion) { diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetFactory.java b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetFactory.java index cd79759f576..5897146fc45 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetFactory.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/DataSetFactory.java @@ -58,6 +58,7 @@ import it.eng.spagobi.tools.dataset.bo.JDBCDatasetFactory; import it.eng.spagobi.tools.dataset.bo.JDBCHiveDataSet; import it.eng.spagobi.tools.dataset.bo.JDBCOrientDbDataSet; +import it.eng.spagobi.tools.dataset.bo.JDBCRedShiftDataSet; import it.eng.spagobi.tools.dataset.bo.JDBCVerticaDataSet; import it.eng.spagobi.tools.dataset.bo.JavaClassDataSet; import it.eng.spagobi.tools.dataset.bo.MongoDataSet; @@ -442,7 +443,18 @@ public static IDataSet toDataSet(SbiDataSet sbiDataSet, IEngUserProfile userProf DataSourceDAOHibImpl dataSourceDao = new DataSourceDAOHibImpl(); if (userProfile != null) dataSourceDao.setUserProfile(userProfile); - IDataSource dataSource = dataSourceDao.loadDataSourceByLabel(jsonConf.getString(DataSetConstants.DATA_SOURCE)); + + /* WORKAROUND : in the past the datasource attribute was + * dataSource and not dataSourceFlat. + */ + String dataSourceName = null; + if (jsonConf.has(DataSetConstants.DATA_SOURCE)) { + dataSourceName = jsonConf.getString(DataSetConstants.DATA_SOURCE); + } else { + dataSourceName = jsonConf.getString(DataSetConstants.DATA_SOURCE_FLAT); + } + + IDataSource dataSource = dataSourceDao.loadDataSourceByLabel(dataSourceName); ((FlatDataSet) ds).setDataSource(dataSource); ((FlatDataSet) ds).setTableName(jsonConf.getString(DataSetConstants.FLAT_TABLE_NAME)); ds.setDsType(FLAT_DS_TYPE); @@ -799,6 +811,8 @@ private static IDataSet getDataset(IDataSource dataSource) { ds = new JDBCOrientDbDataSet(); } else if (dialectToLowerCase.contains("vertica")) { ds = new JDBCVerticaDataSet(); + } else if (dialectToLowerCase.contains("RedShift")) { + ds = new JDBCRedShiftDataSet(); } } return (ds != null) ? ds : new JDBCDataSet(); diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/IBIObjDataSetDAO.java b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/IBIObjDataSetDAO.java index e4e7b4eec33..f8d910c6b2e 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/IBIObjDataSetDAO.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/dataset/dao/IBIObjDataSetDAO.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,32 +11,33 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.dataset.dao; +import java.util.ArrayList; + +import org.hibernate.Session; + import it.eng.spago.error.EMFUserError; import it.eng.spagobi.analiticalmodel.document.bo.BIObject; +import it.eng.spagobi.analiticalmodel.document.bo.ObjTemplate; import it.eng.spagobi.commons.dao.ISpagoBIDao; import it.eng.spagobi.tools.dataset.bo.BIObjDataSet; -import java.util.ArrayList; - -import org.hibernate.Session; - /** * Defines the interfaces for all methods needed to insert, modify and deleting a BI Object DataSet. - * + * * @author Gavardi - * + * */ public interface IBIObjDataSetDAO extends ISpagoBIDao { /** * Update association between object and used datasets - * + * * @param biObjId * @param dsLabels * @return @@ -62,4 +63,6 @@ public interface IBIObjDataSetDAO extends ISpagoBIDao { public void eraseBIObjDataSetByObjectId(Integer biObjId) throws EMFUserError; public void eraseBIObjDataSetByObjectId(Integer biObjId, Session currSession) throws EMFUserError; + + public void insertOrUpdateDatasetDependencies(BIObject biObject, ObjTemplate template, Session session); } \ No newline at end of file diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/IObjMetadataDAO.java b/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/IObjMetadataDAO.java index dbe4bc869aa..4254e326107 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/IObjMetadataDAO.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/IObjMetadataDAO.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,130 +11,130 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.tools.objmetadata.dao; +import java.util.List; + import it.eng.spago.error.EMFUserError; import it.eng.spagobi.commons.dao.ISpagoBIDao; import it.eng.spagobi.tools.objmetadata.bo.ObjMetadata; -import java.util.List; - /** * Defines the interfaces for all methods needed to insert, modify and deleting object's metadata. */ -public interface IObjMetadataDAO extends ISpagoBIDao{ - +public interface IObjMetadataDAO extends ISpagoBIDao { + /** - * Loads all detail information for a metadata identified by its type. - * All these informations, achived by a query to the DB, are stored - * into a metadata object, which is returned. - * + * Loads all detail information for a metadata identified by its type. All these informations, achived by a query to the DB, are stored into a + * metadata object, which is returned. + * * @param type The type of metadata to load (LONG_TEXT or SHORT_TEXT) - * + * * @return A objMetadata object containing all loaded information - * + * * @throws EMFUserError If an Exception occurred */ public List loadObjMetaDataListByType(String type) throws EMFUserError; - + /** - * Loads all detail information for a metadata identified by its id. - * All these information, achived by a query to the DB, are stored - * into a metadata object, which is returned. - * + * Loads all detail information for a metadata identified by its id. All these information, achived by a query to the DB, are stored into a + * metadata object, which is returned. + * * @param id The id for the metadata to load - * + * * @return A objMetadata object containing all loaded information - * + * * @throws EMFUserError If an Exception occurred */ public ObjMetadata loadObjMetaDataByID(Integer id) throws EMFUserError; - + /** * Loads all detail information for object's metadata whose label is equal to label. - * + * * @param label The label for the metadata to load - * + * * @return An ObjMetada object containing all loaded information - * + * * @throws EMFUserError If an Exception occurred */ public ObjMetadata loadObjMetadataByLabel(String label) throws EMFUserError; - + /** - * Loads all detail information for all object's metadata. For each of them, detail - * information is stored into a ObjMetadata object. After that, all metadata - * are stored into a List, which is returned. - * + * Loads all detail information for all object's metadata. For each of them, detail information is stored into a ObjMetadata object. After + * that, all metadata are stored into a List, which is returned. + * * @return A list containing all metadata objects - * + * * @throws EMFUserError If an Exception occurred */ - + public List loadAllObjMetadata() throws EMFUserError; /** - * Implements the query to modify an object's metadata. All information needed is stored - * into the input ObjMetadata object. - * + * Implements the query to modify an object's metadata. All information needed is stored into the input ObjMetadata object. + * * @param aObjMetadata The object containing all modify information - * + * * @throws EMFUserError If an Exception occurred */ - + public void modifyObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError; - + /** - * Implements the query to insert an object's metadata. All information needed is stored - * into the input ObjMetadata object. - * + * Implements the query to insert an object's metadata. All information needed is stored into the input ObjMetadata object. + * * @param aObjMetadata The object containing all insert information - * + * * @throws EMFUserError If an Exception occurred */ public void insertObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError; - + /** - * Implements the query to erase an object's metadata. All information needed is stored - * into the input ObjMetadata object. - * + * Implements the query to erase an object's metadata. All information needed is stored into the input ObjMetadata object. + * * @param aObjMetadata The object containing all delete information - * + * * @throws EMFUserError If an Exception occurred - */ + */ public void eraseObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError; /** - * Tells if a objMetadata is associated to any - * BI Objects. It is useful because a metadata cannot be deleted - * if it is used by one or more BI Objects. - * + * Tells if a objMetadata is associated to any BI Objects. It is useful because a metadata cannot be deleted if it is used by one or more BI Objects. + * * @param id The objMetadata identifier - * - * @return True if the metadata is used by one or more - * objects, else false - * + * + * @return True if the metadata is used by one or more objects, else false + * * @throws EMFUserError If any exception occurred */ - public boolean hasBIObjAssociated (String id) throws EMFUserError; + public boolean hasBIObjAssociated(String id) throws EMFUserError; - /** - * Tells if a objMetadata is associated to any - * BI SubObjects. It is useful because a metadata cannot be deleted - * if it is used by one or more BI SubObjects. - * + * Tells if a objMetadata is associated to any BI SubObjects. It is useful because a metadata cannot be deleted if it is used by one or more BI SubObjects. + * * @param id The objMetadata identifier - * - * @return True if the metadata is used by one or more - * subobjects, else false - * + * + * @return True if the metadata is used by one or more subobjects, else false + * * @throws EMFUserError If any exception occurred */ - public boolean hasSubObjAssociated (String id) throws EMFUserError; + public boolean hasSubObjAssociated(String id) throws EMFUserError; + + public List loadObjMetadataByBIObjectID(Integer biobjId) throws EMFUserError; + + /** + * Load all metadata filtered by label comparison. + * + * @return the list + * + * @throws EMFUserError the EMF user error + * + * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#loadAllObjMetadata() + */ + public List loadAllObjMetadataByLabelAndCase(String label, boolean caseSensitive) throws EMFUserError; } \ No newline at end of file diff --git a/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/ObjMetadataDAOHibImpl.java b/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/ObjMetadataDAOHibImpl.java index 75a09f153a4..5dcf917ad36 100644 --- a/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/ObjMetadataDAOHibImpl.java +++ b/knowagedao/src/main/java/it/eng/spagobi/tools/objmetadata/dao/ObjMetadataDAOHibImpl.java @@ -49,13 +49,11 @@ public class ObjMetadataDAOHibImpl extends AbstractHibernateDAO implements IObjM /** * Load object's metadata by type * - * @param type - * the type(SHORT_TEXT or LONG_TEXT) + * @param type the type(SHORT_TEXT or LONG_TEXT) * * @return the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error */ @Override public List loadObjMetaDataListByType(String type) throws EMFUserError { @@ -103,13 +101,11 @@ public List loadObjMetaDataListByType(String type) throws EMFUserError { /** * Load object's metadata by id. * - * @param id - * the identifier + * @param id the identifier * * @return the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#loadObjMetaDataByID(java.lang.Integer) */ @@ -150,19 +146,16 @@ public ObjMetadata loadObjMetaDataByID(Integer id) throws EMFUserError { /** * Load object's metadata by label. * - * @param label - * the label + * @param label the label * * @return the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#loadObjMetadataByLabel(java.lang.String) */ @Override public ObjMetadata loadObjMetadataByLabel(String label) throws EMFUserError { - logger.debug("IN"); ObjMetadata toReturn = null; Session tmpSession = null; @@ -170,9 +163,10 @@ public ObjMetadata loadObjMetadataByLabel(String label) throws EMFUserError { try { tmpSession = getSession(); tx = tmpSession.beginTransaction(); - Criterion labelCriterrion = Expression.eq("label", label); + Criterion labelCriterion = null; + labelCriterion = Expression.eq("label", label); Criteria criteria = tmpSession.createCriteria(SbiObjMetadata.class); - criteria.add(labelCriterrion); + criteria.add(labelCriterion); SbiObjMetadata hibMeta = (SbiObjMetadata) criteria.uniqueResult(); if (hibMeta == null) return null; @@ -195,13 +189,55 @@ public ObjMetadata loadObjMetadataByLabel(String label) throws EMFUserError { } + @Override + public List loadObjMetadataByBIObjectID(Integer biobjId) throws EMFUserError { + + logger.debug("IN"); + List toReturn = new ArrayList(); + Session aSession = null; + Transaction tx = null; + + try { + aSession = getSession(); + tx = aSession.beginTransaction(); + StringBuilder sb = new StringBuilder(); + sb.append(" select t1 "); + sb.append(" from SbiObjMetadata t1, SbiObjMetacontents t2"); + sb.append(" where t1.objMetaId=t2.objmetaId"); + sb.append(" and t2.sbiObjects.biobjId=" + biobjId); + + List tmpList = aSession.createQuery(sb.toString()).list(); + for (Object obj : tmpList) { + SbiObjMetadata som = (SbiObjMetadata) obj; + toReturn.add(toObjMetadata(som)); + } + tx.commit(); + + } catch (HibernateException he) { + logger.error("Error while loading the metadata with biobjId " + biobjId.toString(), he); + + if (tx != null) + tx.rollback(); + + throw new EMFUserError(EMFErrorSeverity.ERROR, 100); + + } finally { + if (aSession != null) { + if (aSession.isOpen()) + aSession.close(); + logger.debug("OUT"); + } + } + logger.debug("OUT"); + return toReturn; + } + /** * Load all metadata. * * @return the list * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#loadAllObjMetadata() */ @@ -244,14 +280,65 @@ public List loadAllObjMetadata() throws EMFUserError { } + /** + * Load all metadata filtered by label comparison. + * + * @return the list + * + * @throws EMFUserError the EMF user error + * + * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#loadAllObjMetadata() + */ + @Override + public List loadAllObjMetadataByLabelAndCase(String label, boolean caseSensitive) throws EMFUserError { + logger.debug("IN"); + List toReturn = new ArrayList(); + Session tmpSession = null; + Transaction tx = null; + try { + tmpSession = getSession(); + tx = tmpSession.beginTransaction(); + Criterion labelCriterion = null; + if (caseSensitive) { + labelCriterion = Expression.eq("label", label); + } else { + labelCriterion = Expression.eq("label", label).ignoreCase(); + + } + Criteria criteria = tmpSession.createCriteria(SbiObjMetadata.class); + criteria.add(labelCriterion); + List hibMeta = criteria.list(); + if (hibMeta == null) + return null; + + for (Object object : hibMeta) { + + toReturn.add(toObjMetadata((SbiObjMetadata) object)); + } + + tx.commit(); + } catch (HibernateException he) { + logger.error("Error while loading the metadata with label " + label, he); + if (tx != null) + tx.rollback(); + throw new EMFUserError(EMFErrorSeverity.ERROR, 100); + } finally { + if (tmpSession != null) { + if (tmpSession.isOpen()) + tmpSession.close(); + } + } + logger.debug("OUT"); + return toReturn; + + } + /** * Modify metadata. * - * @param aObjMetadata - * the metadata + * @param aObjMetadata the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#modifyObjMetadata(it.eng.spagobi.tools.objmetadata.bo.ObjMetadata) */ @@ -300,11 +387,9 @@ public void modifyObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError { /** * Insert object's metadata. * - * @param aObjMetadata - * the metadata + * @param aObjMetadata the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#insertObjMetadata(it.eng.spagobi.tools.objmetadata.bo.ObjMetadata) */ @@ -356,11 +441,9 @@ public void insertObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError { /** * Erase object's metadata * - * @param aObjMetadata - * the metadata + * @param aObjMetadata the metadata * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#eraseObjMetadata(it.eng.spagobi.tools.objmetadata.bo.ObjMetadata) */ @@ -409,13 +492,11 @@ public void eraseObjMetadata(ObjMetadata aObjMetadata) throws EMFUserError { /** * Checks for bi obj associated. * - * @param id - * the metadata id + * @param id the metadata id * * @return true, if checks for bi obj associated * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#hasBIObjAssociated(java.lang.String) */ @@ -464,13 +545,11 @@ public boolean hasBIObjAssociated(String id) throws EMFUserError { /** * Checks for bi subobject associated. * - * @param id - * the metadata id + * @param id the metadata id * * @return true, if checks for bi subobjects associated * - * @throws EMFUserError - * the EMF user error + * @throws EMFUserError the EMF user error * * @see it.eng.spagobi.tools.objmetadata.dao.IObjMetadataDAO#hasSubObjAssociated(java.lang.String) */ @@ -518,8 +597,7 @@ public boolean hasSubObjAssociated(String id) throws EMFUserError { /** * From the hibernate SbiObjMetadata at input, gives the corrispondent ObjMetadata object. * - * @param hibObjMetadata - * The hybernate metadata + * @param hibObjMetadata The hybernate metadata * * @return The corrispondent ObjMetadata object */ diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/catalogue/metadata/mapping/SbiMetaModel.hbm.xml b/knowagedao/src/main/resources/it/eng/spagobi/tools/catalogue/metadata/mapping/SbiMetaModel.hbm.xml index 3d3a5822fa8..bae91d427a8 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/catalogue/metadata/mapping/SbiMetaModel.hbm.xml +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/catalogue/metadata/mapping/SbiMetaModel.hbm.xml @@ -61,6 +61,9 @@ + + + diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiAttribute.hbm.xml b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiAttribute.hbm.xml index 57a6adf4467..6a44250e995 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiAttribute.hbm.xml +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiAttribute.hbm.xml @@ -3,23 +3,45 @@ "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + it.eng.spagobi.profiling.bo.ProfileAttributesValueTypes + 12 + + + + + + + + + + + + diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiMetaModel.hbm.xml b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiMetaModel.hbm.xml index 4cfe9dc1dfc..feb55f39dc8 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiMetaModel.hbm.xml +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiMetaModel.hbm.xml @@ -25,6 +25,9 @@ + + + diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiUser.hbm.xml b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiUser.hbm.xml index da8cdc715d5..28582e7fa07 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiUser.hbm.xml +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/SbiUser.hbm.xml @@ -23,9 +23,9 @@ - + diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/catalog.script b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/catalog.script index 0dc88e716a8..2f02c3e632e 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/catalog.script +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/catalog.script @@ -4,13 +4,13 @@ CREATE MEMORY TABLE SBI_EXT_ROLES_CATEGORY(EXT_ROLE_ID INTEGER NOT NULL,CATEGORY CREATE MEMORY TABLE SBI_CHECKS(CHECK_ID INTEGER NOT NULL,DESCR VARCHAR,LABEL VARCHAR,VALUE_TYPE_CD VARCHAR,VALUE_TYPE_ID INTEGER,VALUE_1 VARCHAR,VALUE_2 VARCHAR,NAME VARCHAR) CREATE MEMORY TABLE SBI_DOMAINS(VALUE_ID INTEGER NOT NULL,VALUE_CD VARCHAR,VALUE_NM VARCHAR,DOMAIN_CD VARCHAR,DOMAIN_NM VARCHAR,VALUE_DS VARCHAR,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP) CREATE MEMORY TABLE SBI_DATA_SET(DS_ID INTEGER NOT NULL,VERSION_NUM INTEGER NOT NULL,ACTIVE BOOLEAN NOT NULL,DESCR VARCHAR(160),LABEL VARCHAR(50) NOT NULL,NAME VARCHAR(50) NOT NULL,OBJECT_TYPE VARCHAR(50),CONFIGURATION VARCHAR,DS_METADATA VARCHAR,PARAMS VARCHAR(4000),CATEGORY_ID INTEGER,TRANSFORMER_ID INTEGER,PIVOT_COLUMN VARCHAR(50),PIVOT_ROW VARCHAR(50),PIVOT_VALUE VARCHAR(50),NUM_ROWS BOOLEAN DEFAULT false,META_VERSION VARCHAR(100),IS_PERSISTED BOOLEAN DEFAULT FALSE,IS_PERSISTED_HDFS BOOLEAN DEFAULT 0, OWNER VARCHAR(50),USER_IN VARCHAR(100) DEFAULT '' NOT NULL,USER_UP VARCHAR(100),USER_DE VARCHAR(100),TIME_IN TIMESTAMP DEFAULT NOW NOT NULL,TIME_UP TIMESTAMP,TIME_DE TIMESTAMP,SBI_VERSION_IN VARCHAR(10),SBI_VERSION_UP VARCHAR(10),SBI_VERSION_DE VARCHAR(10),ORGANIZATION VARCHAR(20), PERSIST_TABLE_NAME VARCHAR(50), SCOPE_ID INTEGER, FEDERATION_ID INTEGER) -CREATE MEMORY TABLE SBI_OBJ_METADATA(OBJ_META_ID INTEGER NOT NULL,LABEL VARCHAR NOT NULL,NAME VARCHAR NOT NULL,DESCR VARCHAR,DATA_TYPE_ID INTEGER NOT NULL,CREATION_DATE TIMESTAMP) + CREATE MEMORY TABLE SBI_FEDERATION_DEFINITION (FEDERATION_ID INTEGER NOT NULL,LABEL VARCHAR(100) DEFAULT NULL, NAME VARCHAR(100) DEFAULT NULL, DESCRIPTION VARCHAR(100) DEFAULT NULL, RELATIONSHIPS VARCHAR, USER_IN VARCHAR(100) DEFAULT '' NOT NULL, USER_UP VARCHAR(100), USER_DE VARCHAR(100), TIME_IN TIMESTAMP DEFAULT NOW NOT NULL, TIME_UP TIMESTAMP DEFAULT NULL, TIME_DE TIMESTAMP DEFAULT NULL, SBI_VERSION_IN VARCHAR(10), SBI_VERSION_UP VARCHAR(10), SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20)) CREATE MEMORY TABLE SBI_DATA_SET_FEDERATION (FEDERATION_ID INTEGER NOT NULL, DS_ID INTEGER NOT NULL, VERSION_NUM INTEGER, ORGANIZATION VARCHAR(20)) CREATE MEMORY TABLE SBI_DATA_SOURCE(DS_ID INTEGER NOT NULL,DESCR VARCHAR,LABEL VARCHAR NOT NULL,JNDI VARCHAR,URL_CONNECTION VARCHAR,USERNAME VARCHAR,PWD VARCHAR,DRIVER VARCHAR,DIALECT_ID INTEGER NOT NULL,MULTI_SCHEMA boolean default false,ATTR_SCHEMA VARCHAR, READ_ONLY BOOLEAN DEFAULT FALSE, WRITE_DEFAULT BOOLEAN DEFAULT FALSE, JDBC_ADVANCED_CONFIGURATION VARCHAR(4000) DEFAULT NULL) CREATE MEMORY TABLE SBI_META_BC(BC_ID INTEGER NOT NULL,MODEL_ID INTEGER NOT NULL,DELETED BOOLEAN NOT NULL,NAME VARCHAR(100) DEFAULT NULL,UNIQUE_NAME VARCHAR(100) DEFAULT NULL) CREATE MEMORY TABLE SBI_META_DS_BC(DS_ID INTEGER NOT NULL,VERSION_NUM INTEGER NOT NULL,BC_ID INTEGER NOT NULL,ORGANIZATION VARCHAR(20) DEFAULT NULL) -CREATE MEMORY TABLE SBI_META_MODELS(ID INTEGER NOT NULL,NAME VARCHAR(100) NOT NULL,DESCR VARCHAR(500) DEFAULT NULL,CATEGORY_ID INTEGER DEFAULT NULL, MODEL_LOCKED BOOLEAN DEFAULT NULL,MODEL_LOCKER VARCHAR(100) DEFAULT NULL, DATA_SOURCE_ID INTEGER DEFAULT NULL, TABLE_PREFIX_LIKE VARCHAR(4000) DEFAULT NULL, TABLE_PREFIX_NOT_LIKE VARCHAR(4000) DEFAULT NULL) +CREATE MEMORY TABLE SBI_META_MODELS(ID INTEGER NOT NULL,NAME VARCHAR(100) NOT NULL,DESCR VARCHAR(500) DEFAULT NULL,CATEGORY_ID INTEGER DEFAULT NULL, MODEL_LOCKED BOOLEAN DEFAULT NULL,MODEL_LOCKER VARCHAR(100) DEFAULT NULL, DATA_SOURCE_ID INTEGER DEFAULT NULL, TABLE_PREFIX_LIKE VARCHAR(4000) DEFAULT NULL, TABLE_PREFIX_NOT_LIKE VARCHAR(4000) DEFAULT NULL, SMART_VIEW BOOLEAN DEFAULT TRUE) CREATE MEMORY TABLE SBI_META_MODELS_VERSIONS (ID INTEGER NOT NULL,MODEL_ID INTEGER NOT NULL,CONTENT LONGVARBINARY DEFAULT NULL,FILE_MODEL LONGVARBINARY DEFAULT NULL,NAME VARCHAR(100), PROG INTEGER,CREATION_DATE TIMESTAMP DEFAULT NULL,CREATION_USER VARCHAR(50) NOT NULL, ACTIVE BOOLEAN, USER_IN VARCHAR(100) NOT NULL,USER_UP VARCHAR(100),USER_DE VARCHAR(100),TIME_IN TIMESTAMP NOT NULL,TIME_UP TIMESTAMP DEFAULT NULL,TIME_DE TIMESTAMP DEFAULT NULL,SBI_VERSION_IN VARCHAR(10),SBI_VERSION_UP VARCHAR(10),SBI_VERSION_DE VARCHAR(10),META_VERSION VARCHAR(100),ORGANIZATION VARCHAR(20),PRIMARY KEY (ID)) CREATE MEMORY TABLE SBI_METAMODEL_PAR(METAMODEL_PAR_ID INTEGER NOT NULL,PAR_ID INTEGER NOT NULL,METAMODEL_ID INTEGER NOT NULL,LABEL VARCHAR(40) NOT NULL,REQ_FL SMALLINT,MOD_FL SMALLINT,VIEW_FL SMALLINT,MULT_FL SMALLINT,PROG INTEGER NOT NULL,PARURL_NM VARCHAR(20) DEFAULT NULL,PRIORITY INTEGER DEFAULT NULL,COL_SPAN INTEGER,THICK_PERC INTEGER) CREATE MEMORY TABLE SBI_METAMODEL_PARUSE(PARUSE_ID INTEGER NOT NULL,METAMODEL_PAR_ID INTEGER NOT NULL,USE_ID INTEGER NOT NULL,METAMODEL_PAR_FATHER_ID INTEGER,FILTER_OPERATION VARCHAR(20) NOT NULL,PROG INTEGER NOT NULL,FILTER_COLUMN VARCHAR(30) NOT NULL,PRE_CONDITION VARCHAR(10) DEFAULT NULL,POST_CONDITION VARCHAR(10) DEFAULT NULL,LOGIC_OPERATOR VARCHAR(10) DEFAULT NULL) @@ -34,6 +34,17 @@ CREATE MEMORY TABLE SBI_PARUSE_CK(CHECK_ID INTEGER NOT NULL,USE_ID INTEGER NOT N CREATE MEMORY TABLE SBI_PARUSE_DET(EXT_ROLE_ID INTEGER NOT NULL,PROG INTEGER,USE_ID INTEGER NOT NULL,HIDDEN_FL SMALLINT,DEFAULT_VAL VARCHAR) CREATE MEMORY TABLE SBI_LOV(LOV_ID INTEGER NOT NULL,DESCR VARCHAR,LABEL VARCHAR,INPUT_TYPE_CD VARCHAR,DEFAULT_VAL VARCHAR,LOV_PROVIDER VARCHAR,INPUT_TYPE_ID INTEGER,PROFILE_ATTR VARCHAR,NAME VARCHAR,DATASET_ID INTEGER) +CREATE MEMORY TABLE SBI_OBJECTS(BIOBJ_ID INTEGER NOT NULL,ENGINE_ID INTEGER,DESCR VARCHAR,LABEL VARCHAR,ENCRYPT SMALLINT,PATH VARCHAR,REL_NAME VARCHAR,STATE_ID INTEGER,STATE_CD VARCHAR,BIOBJ_TYPE_CD VARCHAR,BIOBJ_TYPE_ID INTEGER,SCHED_FL SMALLINT,EXEC_MODE_ID INTEGER,STATE_CONS_ID INTEGER,EXEC_MODE_CD VARCHAR,STATE_CONS_CD VARCHAR,NAME VARCHAR,VISIBLE SMALLINT,UUID VARCHAR,DATA_SOURCE_ID INTEGER, DESCR_EXT VARCHAR,OBJECTIVE VARCHAR,KEYWORDS VARCHAR,LANGUAGE VARCHAR,CREATION_DATE TIMESTAMP,CREATION_USER VARCHAR,REFRESH_SECONDS INTEGER,PROF_VISIBILITY VARCHAR(400) NULL, PREVIEW_FILE VARCHAR(100), PARAMETERS_REGION VARCHAR(20), LOCKED_BY_USER VARCHAR(100)) +CREATE MEMORY TABLE SBI_FUNCTIONS(FUNCT_ID INTEGER NOT NULL,FUNCT_TYPE_CD VARCHAR,PARENT_FUNCT_ID INTEGER,NAME VARCHAR,DESCR VARCHAR,PATH VARCHAR,CODE VARCHAR,PROG INTEGER NOT NULL,FUNCT_TYPE_ID INTEGER) +CREATE MEMORY TABLE SBI_ENGINES(ENGINE_ID INTEGER NOT NULL,ENCRYPT SMALLINT,NAME VARCHAR,DESCR VARCHAR,MAIN_URL VARCHAR,SECN_URL VARCHAR,OBJ_UPL_DIR VARCHAR,OBJ_USE_DIR VARCHAR,DRIVER_NM VARCHAR,LABEL VARCHAR,ENGINE_TYPE INTEGER,CLASS_NM VARCHAR,BIOBJ_TYPE INTEGER, USE_DATASET BOOLEAN, USE_DATASOURCE BOOLEAN) +CREATE MEMORY TABLE SBI_OBJ_PAR(PAR_ID INTEGER NOT NULL,BIOBJ_ID INTEGER NOT NULL,LABEL VARCHAR,REQ_FL SMALLINT,MOD_FL SMALLINT,VIEW_FL SMALLINT,MULT_FL SMALLINT,PROG INTEGER NOT NULL,PARURL_NM VARCHAR,OBJ_PAR_ID INTEGER NOT NULL,PRIORITY INTEGER, COL_SPAN INTEGER, THICK_PERC INTEGER) +CREATE MEMORY TABLE SBI_IMAGES(IMAGE_ID INTEGER NOT NULL,NAME VARCHAR(100) NOT NULL,CONTENT LONGVARBINARY NOT NULL,CONTENT_ICO LONGVARBINARY, USER_IN VARCHAR(100) DEFAULT '' NOT NULL,USER_UP VARCHAR(100),USER_DE VARCHAR(100),TIME_IN TIMESTAMP DEFAULT NOW NOT NULL,TIME_UP TIMESTAMP,TIME_DE TIMESTAMP,SBI_VERSION_IN VARCHAR(10),SBI_VERSION_UP VARCHAR(10),SBI_VERSION_DE VARCHAR(10),META_VERSION VARCHAR(100),ORGANIZATION VARCHAR(20),CONSTRAINT XPKSBI_OBJ_IMAGES PRIMARY KEY(IMAGE_ID)) +CREATE MEMORY TABLE SBI_OBJ_METADATA(OBJ_META_ID INTEGER NOT NULL,LABEL VARCHAR NOT NULL,NAME VARCHAR NOT NULL,DESCR VARCHAR,DATA_TYPE_ID INTEGER NOT NULL,CREATION_DATE TIMESTAMP) +CREATE MEMORY TABLE SBI_OBJ_METACONTENTS(OBJ_METACONTENT_ID INTEGER NOT NULL,OBJMETA_ID INTEGER NOT NULL,BIOBJ_ID INTEGER NOT NULL, SUBOBJ_ID INTEGER, BIN_ID INTEGER, CREATION_DATE TIMESTAMP NOT NULL, LAST_CHANGE_DATE TIMESTAMP NOT NULL,ADDITIONAL_INFO VARCHAR(255) DEFAULT NULL) +CREATE MEMORY TABLE SBI_CROSS_NAVIGATION(ID INTEGER NOT NULL,NAME VARCHAR(40) NOT NULL, DESCRIPTION VARCHAR(200) DEFAULT NULL, BREADCRUMB VARCHAR(200) DEFAULT NULL, POPUP_OPTIONS VARCHAR(4000) DEFAULT NULL, TYPE INTEGER NOT NULL, FROM_DOC_ID INTEGER DEFAULT NULL, TO_DOC_ID INTEGER DEFAULT NULL) +CREATE MEMORY TABLE SBI_UDP (UDP_ID INTEGER NOT NULL PRIMARY KEY, TYPE_ID INTEGER, FAMILY_ID INTEGER, LABEL VARCHAR NOT NULL, NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NULL,IS_MULTIVALUE BOOLEAN DEFAULT FALSE) +CREATE MEMORY TABLE SBI_UDP_VALUE (UDP_VALUE_ID INTEGER NOT NULL PRIMARY KEY,UDP_ID INTEGER NOT NULL, VALUE VARCHAR, PROG INTEGER NULL, LABEL VARCHAR NOT NULL,NAME VARCHAR NULL, FAMILY VARCHAR NULL, BEGIN_TS TIMESTAMP NOT NULL, END_TS TIMESTAMP NULL, REFERENCE_ID INTEGER NULL); + CREATE USER SA PASSWORD "" GRANT DBA TO SA SET WRITE_DELAY 60 diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/metadata.script b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/metadata.script index c34b8fc5491..3485cf59680 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/metadata.script +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/metadata.script @@ -43,7 +43,7 @@ CREATE MEMORY TABLE SBI_OBJ_METADATA(OBJ_META_ID INTEGER NOT NULL,LABEL VARCHAR CREATE MEMORY TABLE SBI_OBJ_METACONTENTS(OBJ_METACONTENT_ID INTEGER NOT NULL,OBJMETA_ID INTEGER NOT NULL,BIOBJ_ID INTEGER NOT NULL, SUBOBJ_ID INTEGER, BIN_ID INTEGER, CREATION_DATE TIMESTAMP NOT NULL, LAST_CHANGE_DATE TIMESTAMP NOT NULL,ADDITIONAL_INFO VARCHAR(255) DEFAULT NULL) CREATE MEMORY TABLE SBI_UDP (UDP_ID INTEGER NOT NULL PRIMARY KEY, TYPE_ID INTEGER, FAMILY_ID INTEGER, LABEL VARCHAR NOT NULL, NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NULL,IS_MULTIVALUE BOOLEAN DEFAULT FALSE) CREATE MEMORY TABLE SBI_UDP_VALUE (UDP_VALUE_ID INTEGER NOT NULL PRIMARY KEY,UDP_ID INTEGER NOT NULL, VALUE VARCHAR, PROG INTEGER NULL, LABEL VARCHAR NOT NULL,NAME VARCHAR NULL, FAMILY VARCHAR NULL, BEGIN_TS TIMESTAMP NOT NULL, END_TS TIMESTAMP NULL, REFERENCE_ID INTEGER NULL); -CREATE MEMORY TABLE SBI_META_MODELS(ID INTEGER NOT NULL,NAME VARCHAR(100) NOT NULL,DESCR VARCHAR(500) DEFAULT NULL,CATEGORY_ID INTEGER DEFAULT NULL, MODEL_LOCKED BOOLEAN DEFAULT NULL,MODEL_LOCKER VARCHAR(100) DEFAULT NULL, DATA_SOURCE_ID INTEGER DEFAULT NULL, TABLE_PREFIX_LIKE VARCHAR(4000) DEFAULT NULL, TABLE_PREFIX_NOT_LIKE VARCHAR(4000) DEFAULT NULL) +CREATE MEMORY TABLE SBI_META_MODELS(ID INTEGER NOT NULL,NAME VARCHAR(100) NOT NULL,DESCR VARCHAR(500) DEFAULT NULL,CATEGORY_ID INTEGER DEFAULT NULL, MODEL_LOCKED BOOLEAN DEFAULT NULL,MODEL_LOCKER VARCHAR(100) DEFAULT NULL, DATA_SOURCE_ID INTEGER DEFAULT NULL, TABLE_PREFIX_LIKE VARCHAR(4000) DEFAULT NULL, TABLE_PREFIX_NOT_LIKE VARCHAR(4000) DEFAULT NULL, SMART_VIEW BOOLEAN DEFAULT TRUE) CREATE MEMORY TABLE SBI_META_MODELS_VERSIONS (ID INTEGER NOT NULL,MODEL_ID INTEGER NOT NULL,CONTENT LONGVARBINARY DEFAULT NULL,FILE_MODEL LONGVARBINARY DEFAULT NULL,NAME VARCHAR(100), PROG INTEGER,CREATION_DATE TIMESTAMP DEFAULT NULL,CREATION_USER VARCHAR(50) NOT NULL, ACTIVE BOOLEAN, USER_IN VARCHAR(100) NOT NULL,USER_UP VARCHAR(100),USER_DE VARCHAR(100),TIME_IN TIMESTAMP NOT NULL,TIME_UP TIMESTAMP DEFAULT NULL,TIME_DE TIMESTAMP DEFAULT NULL,SBI_VERSION_IN VARCHAR(10),SBI_VERSION_UP VARCHAR(10),SBI_VERSION_DE VARCHAR(10),META_VERSION VARCHAR(100),ORGANIZATION VARCHAR(20),PRIMARY KEY (ID)) CREATE MEMORY TABLE SBI_METAMODEL_PAR(METAMODEL_PAR_ID INTEGER NOT NULL,PAR_ID INTEGER NOT NULL,METAMODEL_ID INTEGER NOT NULL,LABEL VARCHAR(40) NOT NULL,REQ_FL SMALLINT,MOD_FL SMALLINT,VIEW_FL SMALLINT,MULT_FL SMALLINT,PROG INTEGER NOT NULL,PARURL_NM VARCHAR(20) DEFAULT NULL,PRIORITY INTEGER DEFAULT NULL,COL_SPAN INTEGER,THICK_PERC INTEGER) CREATE MEMORY TABLE SBI_METAMODEL_PARUSE(PARUSE_ID INTEGER NOT NULL,METAMODEL_PAR_ID INTEGER NOT NULL,USE_ID INTEGER NOT NULL,METAMODEL_PAR_FATHER_ID INTEGER,FILTER_OPERATION VARCHAR(20) NOT NULL,PROG INTEGER NOT NULL,FILTER_COLUMN VARCHAR(30) NOT NULL,PRE_CONDITION VARCHAR(10) DEFAULT NULL,POST_CONDITION VARCHAR(10) DEFAULT NULL,LOGIC_OPERATOR VARCHAR(10) DEFAULT NULL) @@ -54,9 +54,9 @@ CREATE MEMORY TABLE SBI_ARTIFACTS_VERSIONS (ID INTEGER NOT NULL,ARTIFACT_ID INTE CREATE MEMORY TABLE SBI_FEDERATION_DEFINITION (FEDERATION_ID INTEGER NOT NULL,LABEL VARCHAR(100) DEFAULT NULL, NAME VARCHAR(100) DEFAULT NULL, DESCRIPTION VARCHAR(100) DEFAULT NULL, RELATIONSHIPS VARCHAR, USER_IN VARCHAR(100) DEFAULT '' NOT NULL, USER_UP VARCHAR(100), USER_DE VARCHAR(100), TIME_IN TIMESTAMP DEFAULT NOW NOT NULL, TIME_UP TIMESTAMP DEFAULT NULL, TIME_DE TIMESTAMP DEFAULT NULL, SBI_VERSION_IN VARCHAR(10), SBI_VERSION_UP VARCHAR(10), SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), PRIMARY KEY (FEDERATION_ID)) CREATE MEMORY TABLE SBI_DATA_SET_FEDERATION (FEDERATION_ID INTEGER NOT NULL, DS_ID INTEGER NOT NULL, VERSION_NUM INTEGER, ORGANIZATION VARCHAR(20), PRIMARY KEY (FEDERATION_ID,DS_ID,VERSION_NUM)) -CREATE MEMORY TABLE SBI_USER( USER_ID VARCHAR NOT NULL,PASSWORD VARCHAR DEFAULT NULL,FULL_NAME VARCHAR DEFAULT NULL,ID INTEGER NOT NULL,DT_PWD_BEGIN DATETIME DEFAULT NULL,DT_PWD_END DATETIME DEFAULT NULL,FLG_PWD_BLOCKED TINYINT DEFAULT NULL,DT_LAST_ACCESS DATETIME DEFAULT NULL, FAILED_LOGIN_ATTEMPTS INTEGER DEFAULT 0 NOT NULL, IS_SUPERADMIN TINYINT DEFAULT 0,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP, DEFAULT_ROLE_ID INTEGER DEFAULT NULL) +CREATE MEMORY TABLE SBI_USER( USER_ID VARCHAR NOT NULL,FULL_NAME VARCHAR DEFAULT NULL,ID INTEGER NOT NULL,DT_PWD_BEGIN DATETIME DEFAULT NULL,DT_PWD_END DATETIME DEFAULT NULL,FLG_PWD_BLOCKED TINYINT DEFAULT NULL,DT_LAST_ACCESS DATETIME DEFAULT NULL, FAILED_LOGIN_ATTEMPTS INTEGER DEFAULT 0 NOT NULL, IS_SUPERADMIN TINYINT DEFAULT 0,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP, DEFAULT_ROLE_ID INTEGER DEFAULT NULL) CREATE MEMORY TABLE SBI_USER_ATTRIBUTES( ID INTEGER NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL, ATTRIBUTE_VALUE VARCHAR DEFAULT NULL) -CREATE MEMORY TABLE SBI_ATTRIBUTE(ATTRIBUTE_NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL) +CREATE MEMORY TABLE SBI_ATTRIBUTE(ATTRIBUTE_NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL,ALLOW_USER SMALLINT DEFAULT FALSE,LOV_ID INTEGER NULL,SYNTAX SMALLINT, MULTIVALUE SMALLINT DEFAULT 1,VALUE_TYPE VARCHAR(20)) CREATE MEMORY TABLE SBI_EXT_USER_ROLES(ID INTEGER NOT NULL,EXT_ROLE_ID INTEGER NOT NULL,USER_IN VARCHAR NOT NULL,USER_UP VARCHAR DEFAULT NULL,USER_DE VARCHAR DEFAULT NULL,TIME_IN TIMESTAMP NOT NULL ,TIME_UP TIMESTAMP DEFAULT NULL,TIME_DE TIMESTAMP DEFAULT NULL,SBI_VERSION_IN VARCHAR DEFAULT NULL,SBI_VERSION_UP VARCHAR DEFAULT NULL, SBI_VERSION_DE VARCHAR DEFAULT NULL,META_VERSION VARCHAR DEFAULT NULL) CREATE MEMORY TABLE SBI_CROSS_NAVIGATION(ID INTEGER NOT NULL,NAME VARCHAR(40) NOT NULL, DESCRIPTION VARCHAR(200) DEFAULT NULL, BREADCRUMB VARCHAR(200) DEFAULT NULL, POPUP_OPTIONS VARCHAR(4000) DEFAULT NULL, TYPE INTEGER NOT NULL, FROM_DOC_ID INTEGER DEFAULT NULL, TO_DOC_ID INTEGER DEFAULT NULL) diff --git a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/user.script b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/user.script index 996dcb2cd5f..3344dac0157 100644 --- a/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/user.script +++ b/knowagedao/src/main/resources/it/eng/spagobi/tools/importexport/metadata/exportdb/user.script @@ -3,9 +3,9 @@ CREATE MEMORY TABLE SBI_EXT_ROLES(EXT_ROLE_ID INTEGER NOT NULL,NAME VARCHAR,DES CREATE MEMORY TABLE SBI_EXT_ROLES_CATEGORY(EXT_ROLE_ID INTEGER NOT NULL,CATEGORY_ID INTEGER NOT NULL,PRIMARY KEY(EXT_ROLE_ID,CATEGORY_ID)) CREATE MEMORY TABLE SBI_DOMAINS(VALUE_ID INTEGER NOT NULL,VALUE_CD VARCHAR,VALUE_NM VARCHAR,DOMAIN_CD VARCHAR,DOMAIN_NM VARCHAR,VALUE_DS VARCHAR,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP) CREATE MEMORY TABLE SBI_FUNC_ROLE(ROLE_ID INTEGER NOT NULL,FUNCT_ID INTEGER NOT NULL,STATE_CD VARCHAR,STATE_ID INTEGER NOT NULL) -CREATE MEMORY TABLE SBI_USER( USER_ID VARCHAR NOT NULL,PASSWORD VARCHAR DEFAULT NULL,FULL_NAME VARCHAR DEFAULT NULL,ID INTEGER NOT NULL,DT_PWD_BEGIN DATETIME DEFAULT NULL,DT_PWD_END DATETIME DEFAULT NULL,FLG_PWD_BLOCKED TINYINT DEFAULT NULL,DT_LAST_ACCESS DATETIME DEFAULT NULL, FAILED_LOGIN_ATTEMPTS INTEGER DEFAULT 0 NOT NULL, IS_SUPERADMIN TINYINT DEFAULT 0,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP, ORGANIZATION VARCHAR DEFAULT NULL, DEFAULT_ROLE_ID INTEGER DEFAULT NULL) +CREATE MEMORY TABLE SBI_USER( USER_ID VARCHAR NOT NULL,FULL_NAME VARCHAR DEFAULT NULL,ID INTEGER NOT NULL,DT_PWD_BEGIN DATETIME DEFAULT NULL,DT_PWD_END DATETIME DEFAULT NULL,FLG_PWD_BLOCKED TINYINT DEFAULT NULL,DT_LAST_ACCESS DATETIME DEFAULT NULL, FAILED_LOGIN_ATTEMPTS INTEGER DEFAULT 0 NOT NULL, IS_SUPERADMIN TINYINT DEFAULT 0,TIME_IN TIMESTAMP, TIME_UP TIMESTAMP, ORGANIZATION VARCHAR DEFAULT NULL, DEFAULT_ROLE_ID INTEGER DEFAULT NULL) CREATE MEMORY TABLE SBI_USER_ATTRIBUTES( ID INTEGER NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL, ATTRIBUTE_VALUE VARCHAR DEFAULT NULL) -CREATE MEMORY TABLE SBI_ATTRIBUTE(ATTRIBUTE_NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL) +CREATE MEMORY TABLE SBI_ATTRIBUTE(ATTRIBUTE_NAME VARCHAR NOT NULL, DESCRIPTION VARCHAR NOT NULL, ATTRIBUTE_ID INTEGER NOT NULL,ALLOW_USER SMALLINT DEFAULT FALSE,LOV_ID INTEGER NULL,SYNTAX SMALLINT, MULTIVALUE SMALLINT DEFAULT 1,VALUE_TYPE VARCHAR(20)) CREATE MEMORY TABLE SBI_EXT_USER_ROLES(ID INTEGER NOT NULL,EXT_ROLE_ID INTEGER NOT NULL,USER_IN VARCHAR NOT NULL,USER_UP VARCHAR DEFAULT NULL,USER_DE VARCHAR DEFAULT NULL,TIME_IN TIMESTAMP NOT NULL ,TIME_UP TIMESTAMP DEFAULT NULL,TIME_DE TIMESTAMP DEFAULT NULL,SBI_VERSION_IN VARCHAR DEFAULT NULL,SBI_VERSION_UP VARCHAR DEFAULT NULL, SBI_VERSION_DE VARCHAR DEFAULT NULL,META_VERSION VARCHAR DEFAULT NULL,ORGANIZATION VARCHAR DEFAULT NULL ) CREATE USER SA PASSWORD "" GRANT DBA TO SA diff --git a/knowagedatabasescripts/hystory_mysql.txt b/knowagedatabasescripts/hystory_mysql.txt index befd1159d70..5a22879e377 100644 --- a/knowagedatabasescripts/hystory_mysql.txt +++ b/knowagedatabasescripts/hystory_mysql.txt @@ -4576,4 +4576,17 @@ ALTER TABLE SBI_CROSS_NAVIGATION ADD COLUMN POPUP_OPTIONS VARCHAR(4000) NULL DEF -- 14/02/2020 Alberto Nale ALTER TABLE SBI_MENU ADD ICON VARCHAR(1000) NULL; -ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; \ No newline at end of file +ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD COLUMN SMART_VIEW BOOLEAN DEFAULT TRUE; diff --git a/knowagedatabasescripts/hystory_oracle.txt b/knowagedatabasescripts/hystory_oracle.txt index 5e28b74c0b1..c8aa94cda1d 100644 --- a/knowagedatabasescripts/hystory_oracle.txt +++ b/knowagedatabasescripts/hystory_oracle.txt @@ -742,3 +742,16 @@ ALTER TABLE SBI_USER ADD CONSTRAINT FK_SBI_USER_1 FOREIGN KEY (DEFAULT_ROLE_ID) -- 9/12/2019 Pirkovic Dragan -- ALTER TABLE SBI_CROSS_NAVIGATION ADD POPUP_OPTIONS VARCHAR(4000) DEFAULT NULL; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD SMART_VIEW SMALLINT DEFAULT 1; diff --git a/knowagedatabasescripts/hystory_postgres.txt b/knowagedatabasescripts/hystory_postgres.txt index 3e70d6c0df7..5e043e94fc9 100644 --- a/knowagedatabasescripts/hystory_postgres.txt +++ b/knowagedatabasescripts/hystory_postgres.txt @@ -4236,3 +4236,22 @@ ALTER TABLE SBI_CROSS_NAVIGATION ADD CONSTRAINT FK_SBI_CROSS_NAVIGATION_2 FOREIG -- 25/02/2020 Radmila Selakovic ALTER TABLE SBI_MENU ADD ICON VARCHAR(255) NULL; ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; + +--14/04/2020 Radmila Selakovic KNOWAGE-5009 +UPDATE SBI_ALERT_LISTENER SET TEMPLATE='angular_1.4/tools/alert/listeners/kpiListener/templates/kpiListener.html' WHERE NAME='KPI Listener'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/executeETL/templates/executeETL.html' WHERE NAME= 'Execute ETL Document'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/sendMail/templates/sendMail.html' WHERE NAME= 'Send mail'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/contextBroker/templates/contextBroker.html' WHERE NAME= 'Context Broker'; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD COLUMN SMART_VIEW BOOLEAN DEFAULT TRUE; diff --git a/knowagedatabasescripts/mysql/MySQL_create.sql b/knowagedatabasescripts/mysql/MySQL_create.sql index 4f4df4c6777..71b0158de65 100644 --- a/knowagedatabasescripts/mysql/MySQL_create.sql +++ b/knowagedatabasescripts/mysql/MySQL_create.sql @@ -155,7 +155,7 @@ CREATE TABLE SBI_FUNCTIONS ( CREATE TABLE SBI_LOV ( - LOV_ID INTEGER NOT NULL , + LOV_ID INTEGER NOT NULL, DESCR VARCHAR(160) NULL, LABEL VARCHAR(20) NOT NULL, INPUT_TYPE_CD VARCHAR(20) NOT NULL, @@ -177,6 +177,7 @@ CREATE TABLE SBI_LOV ( ORGANIZATION VARCHAR(20), DATASET_ID INT(11), UNIQUE XAK1SBI_LOV (LABEL, ORGANIZATION), + UNIQUE XAK2SBI_LOV (NAME, ORGANIZATION), PRIMARY KEY (LOV_ID) ) ENGINE=InnoDB; @@ -289,6 +290,7 @@ CREATE TABLE SBI_OBJECTS ( META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), UNIQUE XAK1SBI_OBJECTS (LABEL, ORGANIZATION), + UNIQUE XAK2SBI_OBJECTS (NAME, ORGANIZATION), PRIMARY KEY (BIOBJ_ID) ) ENGINE=InnoDB; @@ -337,6 +339,7 @@ CREATE TABLE SBI_PARAMETERS ( META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), UNIQUE XAK1SBI_PARAMETERS (LABEL, ORGANIZATION), + UNIQUE XAK2SBI_PARAMETERS (NAME, ORGANIZATION), PRIMARY KEY (PAR_ID) ) ENGINE=InnoDB; @@ -453,6 +456,7 @@ CREATE TABLE SBI_OBJ_PARUSE ( SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), + UNIQUE XAK1SBI_OBJ_PARUSE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY(PARUSE_ID) ) ENGINE=InnoDB; @@ -1055,7 +1059,7 @@ CREATE TABLE SBI_OBJ_METACONTENTS ( CREATE TABLE SBI_CONFIG ( - ID INTEGER NOT NULL , + ID INTEGER NOT NULL, LABEL VARCHAR(100) NOT NULL, NAME VARCHAR(100) NULL, DESCRIPTION VARCHAR(500) NULL, @@ -1289,6 +1293,7 @@ CREATE TABLE SBI_META_MODELS ( DESCR VARCHAR(500) NULL, MODEL_LOCKED TINYINT(1) NULL DEFAULT NULL, MODEL_LOCKER VARCHAR(100) NULL DEFAULT NULL, + SMART_VIEW BOOLEAN DEFAULT TRUE, USER_IN VARCHAR(100) NOT NULL, USER_UP VARCHAR(100), USER_DE VARCHAR(100), @@ -2982,6 +2987,7 @@ CREATE TABLE SBI_METAMODEL_PARUSE ( SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), + UNIQUE XAK1SBI_METAMODEL_PARUSE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY(PARUSE_ID) ) ENGINE=InnoDB; diff --git a/knowagedatabasescripts/mysql/MySQL_drop.sql b/knowagedatabasescripts/mysql/MySQL_drop.sql index e6cb6c88157..7e2e94a4dbc 100644 --- a/knowagedatabasescripts/mysql/MySQL_drop.sql +++ b/knowagedatabasescripts/mysql/MySQL_drop.sql @@ -148,4 +148,22 @@ DROP TABLE IF EXISTS SBI_ACCESSIBILITY_PREFERENCES CASCADE; DROP TABLE IF EXISTS SBI_DOSSIER_ACTIVITY CASCADE; +DROP TABLE IF EXISTS SBI_DATA_SET_TAG CASCADE; + +DROP TABLE IF EXISTS SBI_METAMODEL_PAR CASCADE; + +DROP TABLE IF EXISTS SBI_METAMODEL_PARUSE CASCADE; + +DROP TABLE IF EXISTS SBI_METAMODEL_PARVIEW CASCADE; + +DROP TABLE IF EXISTS SBI_METAMODEL_VIEWPOINTS CASCADE; + +DROP TABLE IF EXISTS SBI_NEWS CASCADE; + +DROP TABLE IF EXISTS SBI_NEWS_READ CASCADE; + +DROP TABLE IF EXISTS SBI_NEWS_ROLES CASCADE; + +DROP TABLE IF EXISTS SBI_TAG CASCADE; + SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file diff --git a/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.0_to_7.1/MySQL_upgradescript_7.0_to_7.1.sql b/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.0_to_7.1/MySQL_upgradescript_7.0_to_7.1.sql index 2b4dea08929..9b6d4694f11 100644 --- a/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.0_to_7.1/MySQL_upgradescript_7.0_to_7.1.sql +++ b/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.0_to_7.1/MySQL_upgradescript_7.0_to_7.1.sql @@ -1 +1 @@ -DELETE FROM SBI_ROLE_TYPE_USER_FUNC WHERE USER_FUNCT_ID IN (SELECT USER_FUNCT_ID FROM SBI_USER_FUNC WHERE NAME IN ('ProfileAttributeManagement','ProfileManagement')) AND ROLE_TYPE_ID = (SELECT VALUE_ID FROM SBI_DOMAINS WHERE DOMAIN_CD='ROLE_TYPE' AND VALUE_CD='DEV_ROLE') +DELETE FROM SBI_ROLE_TYPE_USER_FUNC WHERE USER_FUNCT_ID IN (SELECT USER_FUNCT_ID FROM SBI_USER_FUNC WHERE NAME IN ('ProfileAttributeManagement','ProfileManagement')) AND ROLE_TYPE_ID = (SELECT VALUE_ID FROM SBI_DOMAINS WHERE DOMAIN_CD='ROLE_TYPE' AND VALUE_CD='DEV_ROLE'); \ No newline at end of file diff --git a/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.1_to_7.2/MySQL_upgradescript_7.1_to_7.2.sql b/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.1_to_7.2/MySQL_upgradescript_7.1_to_7.2.sql index c529c2a8df4..ffa10556739 100644 --- a/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.1_to_7.2/MySQL_upgradescript_7.1_to_7.2.sql +++ b/knowagedatabasescripts/mysql/mysql-dbupgradescript-7.1_to_7.2/MySQL_upgradescript_7.1_to_7.2.sql @@ -12,4 +12,23 @@ ALTER TABLE SBI_CROSS_NAVIGATION ADD COLUMN POPUP_OPTIONS VARCHAR(4000) NULL DEF -- 14/02/2020 Alberto Nale ALTER TABLE SBI_MENU ADD ICON VARCHAR(1000) NULL; -ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; \ No newline at end of file +ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; + +-- 2020/04/10 Alberto Nale +UPDATE SBI_ALERT_LISTENER SET TEMPLATE='angular_1.4/tools/alert/listeners/kpiListener/templates/kpiListener.html' WHERE NAME='KPI Listener'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/executeETL/templates/executeETL.html' WHERE NAME= 'Execute ETL Document'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/sendMail/templates/sendMail.html' WHERE NAME= 'Send mail'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/contextBroker/templates/contextBroker.html' WHERE NAME= 'Context Broker'; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD COLUMN SMART_VIEW BOOLEAN DEFAULT TRUE; diff --git a/knowagedatabasescripts/oracle/ORA_create.sql b/knowagedatabasescripts/oracle/ORA_create.sql index 7be43454c7c..ea3c99410b2 100644 --- a/knowagedatabasescripts/oracle/ORA_create.sql +++ b/knowagedatabasescripts/oracle/ORA_create.sql @@ -176,6 +176,7 @@ CREATE TABLE SBI_LOV ( ORGANIZATION VARCHAR2(20), DATASET_ID INTEGER, CONSTRAINT XAK1SBI_LOV UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (LOV_ID) ); @@ -289,6 +290,7 @@ CREATE TABLE SBI_OBJECTS ( META_VERSION VARCHAR2(100), ORGANIZATION VARCHAR2(20), CONSTRAINT XAK1SBI_OBJECTS UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (BIOBJ_ID) ); @@ -338,6 +340,7 @@ CREATE TABLE SBI_PARAMETERS ( META_VERSION VARCHAR2(100), ORGANIZATION VARCHAR2(20), CONSTRAINT XAK1SBI_PARAMETERS UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (PAR_ID) ); @@ -457,6 +460,7 @@ CREATE TABLE SBI_OBJ_PARUSE ( SBI_VERSION_DE VARCHAR2(10), META_VERSION VARCHAR2(100), ORGANIZATION VARCHAR2(20), + CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY (PARUSE_ID) ); @@ -1291,6 +1295,7 @@ CREATE TABLE SBI_META_MODELS ( DESCR VARCHAR2(500) NULL, MODEL_LOCKED SMALLINT NULL, MODEL_LOCKER VARCHAR2(100) NULL, + SMART_VIEW SMALLINT DEFAULT 1, USER_IN VARCHAR2(100) NOT NULL, USER_UP VARCHAR2(100), USER_DE VARCHAR2(100), @@ -2950,6 +2955,7 @@ CREATE TABLE SBI_METAMODEL_PARUSE ( SBI_VERSION_DE VARCHAR2(10), META_VERSION VARCHAR2(100), ORGANIZATION VARCHAR2(20), + CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY (PARUSE_ID) ); diff --git a/knowagedatabasescripts/oracle/ORA_drop.sql b/knowagedatabasescripts/oracle/ORA_drop.sql index 16b05848060..bb48835f6ed 100644 --- a/knowagedatabasescripts/oracle/ORA_drop.sql +++ b/knowagedatabasescripts/oracle/ORA_drop.sql @@ -139,4 +139,10 @@ DROP TABLE SBI_FUNCTION_INPUT_FILE CASCADE CONSTRAINTS; DROP TABLE SBI_DOSSIER_ACTIVITY CASCADE CONSTRAINTS; DROP TABLE SBI_NEWS_ROLES CASCADE CONSTRAINTS; DROP TABLE SBI_NEWS_READ CASCADE CONSTRAINTS; -DROP TABLE SBI_NEWS CASCADE CONSTRAINTS; \ No newline at end of file +DROP TABLE SBI_NEWS CASCADE CONSTRAINTS; +DROP TABLE SBI_TAG CASCADE CONSTRAINTS; +DROP TABLE SBI_METAMODEL_VIEWPOINTS CASCADE CONSTRAINTS; +DROP TABLE SBI_METAMODEL_PARVIEW CASCADE CONSTRAINTS; +DROP TABLE SBI_METAMODEL_PARUSE CASCADE CONSTRAINTS; +DROP TABLE SBI_METAMODEL_PAR CASCADE CONSTRAINTS; +DROP TABLE SBI_DATA_SET_TAG CASCADE CONSTRAINTS; \ No newline at end of file diff --git a/knowagedatabasescripts/oracle/oracle-dbupgradescript-7.1_to_7.2/ORA-dbupgradescript-7.1_to_7.2.sql b/knowagedatabasescripts/oracle/oracle-dbupgradescript-7.1_to_7.2/ORA-dbupgradescript-7.1_to_7.2.sql index 68ff5ad0c2a..e2d648caceb 100644 --- a/knowagedatabasescripts/oracle/oracle-dbupgradescript-7.1_to_7.2/ORA-dbupgradescript-7.1_to_7.2.sql +++ b/knowagedatabasescripts/oracle/oracle-dbupgradescript-7.1_to_7.2/ORA-dbupgradescript-7.1_to_7.2.sql @@ -12,4 +12,17 @@ ALTER TABLE SBI_CROSS_NAVIGATION ADD POPUP_OPTIONS VARCHAR(4000) DEFAULT NULL; -- 14/02/2020 Alberto Nale ALTER TABLE SBI_MENU ADD ICON VARCHAR2(1000) NULL; -ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR2(4000) NULL; \ No newline at end of file +ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR2(4000) NULL; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD SMART_VIEW SMALLINT DEFAULT 1; diff --git a/knowagedatabasescripts/postgres/PG_create.sql b/knowagedatabasescripts/postgres/PG_create.sql index 19787c620ee..553f3eb944c 100644 --- a/knowagedatabasescripts/postgres/PG_create.sql +++ b/knowagedatabasescripts/postgres/PG_create.sql @@ -177,6 +177,7 @@ CREATE TABLE SBI_LOV ( ORGANIZATION VARCHAR(20), DATASET_ID INTEGER, CONSTRAINT XAK1SBI_LOV UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (LOV_ID) ) WITHOUT OIDS; @@ -289,6 +290,7 @@ CREATE TABLE SBI_OBJECTS ( META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), CONSTRAINT XAK1SBI_OBJECTS UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (BIOBJ_ID) ) WITHOUT OIDS; @@ -388,6 +390,7 @@ CREATE TABLE SBI_OBJ_PARUSE ( SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), + CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY(PARUSE_ID) ) WITHOUT OIDS; @@ -1161,6 +1164,7 @@ CREATE TABLE SBI_UDP_VALUE ( )WITHOUT OIDS; CREATE TABLE SBI_OBJ_PARVIEW ( + PARVIEW_ID INTEGER NOT NULL, OBJ_PAR_ID INTEGER NOT NULL, OBJ_PAR_FATHER_ID INTEGER NOT NULL, OPERATION VARCHAR(20) NOT NULL, @@ -1227,6 +1231,7 @@ CREATE TABLE SBI_META_MODELS ( DESCR VARCHAR(500) NULL, MODEL_LOCKED BOOLEAN NULL, MODEL_LOCKER VARCHAR(100) NULL, + SMART_VIEW BOOLEAN DEFAULT TRUE, USER_IN VARCHAR(100) NOT NULL, USER_UP VARCHAR(100), USER_DE VARCHAR(100), @@ -2012,6 +2017,7 @@ CREATE TABLE SBI_PARAMETERS ( META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), CONSTRAINT XAK1SBI_PARAMETERS UNIQUE (LABEL, ORGANIZATION), + CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION), PRIMARY KEY (PAR_ID) ) WITHOUT OIDS; @@ -2987,6 +2993,7 @@ CREATE TABLE SBI_METAMODEL_PARUSE ( SBI_VERSION_DE VARCHAR(10), META_VERSION VARCHAR(100), ORGANIZATION VARCHAR(20), + CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION), PRIMARY KEY(PARUSE_ID) ) WITHOUT OIDS; diff --git a/knowagedatabasescripts/postgres/PG_drop.sql b/knowagedatabasescripts/postgres/PG_drop.sql index c9763ecce30..3af589d61f2 100644 --- a/knowagedatabasescripts/postgres/PG_drop.sql +++ b/knowagedatabasescripts/postgres/PG_drop.sql @@ -167,4 +167,13 @@ DROP TABLE IF EXISTS SBI_FUNCTIONS_ORGANIZER CASCADE; DROP TABLE IF EXISTS SBI_WHATIF_WORKFLOW CASCADE; DROP TABLE IF EXISTS SBI_ACCESSIBILITY_PREFERENCES CASCADE; DROP TABLE IF EXISTS SBI_FUNCTION_INPUT_FILE CASCADE; -DROP TABLE IF EXISTS SBI_DOSSIER_ACTIVITY CASCADE; \ No newline at end of file +DROP TABLE IF EXISTS SBI_DOSSIER_ACTIVITY CASCADE; +DROP TABLE IF EXISTS SBI_DATA_SET_TAG CASCADE; +DROP TABLE IF EXISTS SBI_METAMODEL_PAR CASCADE; +DROP TABLE IF EXISTS SBI_METAMODEL_PARUSE CASCADE; +DROP TABLE IF EXISTS SBI_METAMODEL_PARVIEW CASCADE; +DROP TABLE IF EXISTS SBI_METAMODEL_VIEWPOINTS CASCADE; +DROP TABLE IF EXISTS SBI_NEWS CASCADE; +DROP TABLE IF EXISTS SBI_NEWS_READ CASCADE; +DROP TABLE IF EXISTS SBI_NEWS_ROLES CASCADE; +DROP TABLE IF EXISTS SBI_TAG CASCADE; \ No newline at end of file diff --git a/knowagedatabasescripts/postgres/postgres-dbupgradescript-7.1_to_7.2/PG_upgradescript_7.1_to_7.2.sql b/knowagedatabasescripts/postgres/postgres-dbupgradescript-7.1_to_7.2/PG_upgradescript_7.1_to_7.2.sql index ff8a183ef17..52019ab27cb 100644 --- a/knowagedatabasescripts/postgres/postgres-dbupgradescript-7.1_to_7.2/PG_upgradescript_7.1_to_7.2.sql +++ b/knowagedatabasescripts/postgres/postgres-dbupgradescript-7.1_to_7.2/PG_upgradescript_7.1_to_7.2.sql @@ -14,3 +14,22 @@ ALTER TABLE SBI_CROSS_NAVIGATION ADD CONSTRAINT FK_SBI_CROSS_NAVIGATION_2 FOREIG -- 25/02/2020 Radmila Selakovic ALTER TABLE SBI_MENU ADD ICON VARCHAR(255) NULL; ALTER TABLE SBI_MENU ADD CUST_ICON VARCHAR(4000) NULL; + +--14/04/2020 Radmila Selakovic KNOWAGE-5009 +UPDATE SBI_ALERT_LISTENER SET TEMPLATE='angular_1.4/tools/alert/listeners/kpiListener/templates/kpiListener.html' WHERE NAME='KPI Listener'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/executeETL/templates/executeETL.html' WHERE NAME= 'Execute ETL Document'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/sendMail/templates/sendMail.html' WHERE NAME= 'Send mail'; +UPDATE SBI_ALERT_ACTION SET TEMPLATE='angular_1.4/tools/alert/actions/contextBroker/templates/contextBroker.html' WHERE NAME= 'Context Broker'; + +--08/06/2020 Andrijana Predojevic +ALTER TABLE SBI_OBJ_PARUSE ADD CONSTRAINT XAK1SBI_OBJ_PARUSE UNIQUE (OBJ_PAR_ID,USE_ID,OBJ_PAR_FATHER_ID,FILTER_OPERATION); + +--09/06/2020 Andrijana Predojevic +ALTER TABLE SBI_METAMODEL_PARUSE ADD CONSTRAINT XAK1SBI_METAMODEL_PARUSE UNIQUE (METAMODEL_PAR_ID,USE_ID,METAMODEL_PAR_FATHER_ID,FILTER_OPERATION); + +ALTER TABLE SBI_OBJECTS ADD CONSTRAINT XAK2SBI_OBJECTS UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_LOV ADD CONSTRAINT XAK2SBI_LOV UNIQUE (NAME, ORGANIZATION); +ALTER TABLE SBI_PARAMETERS ADD CONSTRAINT XAK2SBI_PARAMETERS UNIQUE (NAME, ORGANIZATION); + +--15/06/2020 Andrijana Predojevic +ALTER TABLE SBI_META_MODELS ADD COLUMN SMART_VIEW BOOLEAN DEFAULT TRUE; diff --git a/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 5baa9837fc0..00000000000 --- a/knowagedataminingengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagedataminingengine/src/main/webapp/META-INF/context.xml b/knowagedataminingengine/src/main/webapp/META-INF/context.xml index ca5a9d0d553..ddb931dbe51 100644 --- a/knowagedataminingengine/src/main/webapp/META-INF/context.xml +++ b/knowagedataminingengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - + + diff --git a/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 5baa9837fc0..00000000000 --- a/knowagegeoreportengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagegeoreportengine/src/main/webapp/META-INF/context.xml b/knowagegeoreportengine/src/main/webapp/META-INF/context.xml index 8fe8cece37a..48c534ed454 100644 --- a/knowagegeoreportengine/src/main/webapp/META-INF/context.xml +++ b/knowagegeoreportengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - + + diff --git a/knowagegeoreportengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowagegeoreportengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index 9c643ed3565..eb8338def9e 100644 --- a/knowagegeoreportengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowagegeoreportengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -15,7 +15,7 @@ - "> + "> diff --git a/knowagegooglesecurityprovider/pom.xml b/knowagegooglesecurityprovider/pom.xml new file mode 100644 index 00000000000..f38de645eed --- /dev/null +++ b/knowagegooglesecurityprovider/pom.xml @@ -0,0 +1,39 @@ + + 4.0.0 + + + it.eng.knowage + knowage-ce-parent + 7.2.0-SNAPSHOT + ../knowage-ce-parent/pom.xml + + + knowagegooglesecurityprovider + jar + + + + + it.eng.knowage + knowage-dao + 7.2.0-SNAPSHOT + compile + + + + it.eng.knowage + knowage-core + 7.2.0-SNAPSHOT + compile + + + + com.google.api-client + google-api-client + 1.30.4 + + + + + \ No newline at end of file diff --git a/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/GoogleSecurityServiceSupplier.java b/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/GoogleSecurityServiceSupplier.java new file mode 100644 index 00000000000..959e694fac7 --- /dev/null +++ b/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/GoogleSecurityServiceSupplier.java @@ -0,0 +1,118 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.spagobi.security; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; + +import org.apache.log4j.LogMF; +import org.apache.log4j.Logger; + +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload; +import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier; +import com.google.api.client.http.javanet.NetHttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; + +import it.eng.spagobi.security.google.config.GoogleSignInConfig; +import it.eng.spagobi.services.common.JWTSsoService; +import it.eng.spagobi.services.security.bo.SpagoBIUserProfile; +import it.eng.spagobi.services.security.service.ISecurityServiceSupplier; + +public class GoogleSecurityServiceSupplier implements ISecurityServiceSupplier { + + private static int USER_JWT_TOKEN_EXPIRE_HOURS = 10; // JWT token for regular users will expire in 10 HOURS + + static private Logger logger = Logger.getLogger(GoogleSecurityServiceSupplier.class); + + @Override + public SpagoBIUserProfile checkAuthentication(String userId, String psw) { + throw new UnsupportedOperationException(); + } + + @Override + public SpagoBIUserProfile createUserProfile(String jwtToken) { + return new InternalSecurityServiceSupplierImpl().createUserProfile(jwtToken); + } + + @Override + public SpagoBIUserProfile checkAuthenticationWithToken(String userId, String token) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean checkAuthorization(String userId, String function) { + throw new UnsupportedOperationException(); + } + + @Override + public SpagoBIUserProfile checkAuthenticationToken(String token) { + logger.debug("IN"); + LogMF.debug(logger, "Verifying token [{0}]...", token); + GoogleIdToken idToken; + try { + idToken = verifyToken(token); + } catch (GeneralSecurityException | IOException e) { + logger.error("An exception occurred while verifying Google token [" + token + "]", e); + return null; + } + if (idToken == null) { + logger.error("Invalid ID token [" + token + "]"); + return null; + } + LogMF.debug(logger, "Token [{0}] verified successfully", token); + + Payload payload = idToken.getPayload(); + + String userId = payload.getSubject(); + LogMF.debug(logger, "User ID: [{0}]", userId); + String email = payload.getEmail(); + LogMF.debug(logger, "User email: [{0}]", email); + String name = (String) payload.get("name"); + LogMF.debug(logger, "User name: [{0}]", name); + LogMF.debug(logger, "Creating user profile object for user [{0}]...", email); + SpagoBIUserProfile profile = createUserProfileObject(email); + LogMF.debug(logger, "User profile object for user [{0}] created", email); + return profile; + } + + private GoogleIdToken verifyToken(String token) throws GeneralSecurityException, IOException { + GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance()) + .setAudience(Collections.singletonList(GoogleSignInConfig.getClientId())).build(); + GoogleIdToken idToken = verifier.verify(token); + return idToken; + } + + private SpagoBIUserProfile createUserProfileObject(String email) { + SpagoBIUserProfile profile = new SpagoBIUserProfile(); + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.HOUR, USER_JWT_TOKEN_EXPIRE_HOURS); + Date expiresAt = calendar.getTime(); + + String jwtToken = JWTSsoService.userId2jwtToken(email, expiresAt); + + profile.setUniqueIdentifier(jwtToken); + return profile; + } + +} \ No newline at end of file diff --git a/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/google/config/GoogleSignInConfig.java b/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/google/config/GoogleSignInConfig.java new file mode 100644 index 00000000000..ac49599e587 --- /dev/null +++ b/knowagegooglesecurityprovider/src/main/java/it/eng/spagobi/security/google/config/GoogleSignInConfig.java @@ -0,0 +1,76 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.security.google.config; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.Properties; + +import org.apache.log4j.LogMF; +import org.apache.log4j.Logger; + +import it.eng.spagobi.utilities.assertion.Assert; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +public class GoogleSignInConfig { + + static private Logger logger = Logger.getLogger(GoogleSignInConfig.class); + + static protected final String GOOGLE_AUTHENTICATION_CONFIG = "google.signin.config"; + + static protected final String GOOGLE_CLIENT_ID = "client_id"; + + static protected Properties properties = new Properties(); + + static { + try { + String filename = System.getProperty(GOOGLE_AUTHENTICATION_CONFIG); + if (filename != null) { + logger.info("Retrieved " + GOOGLE_AUTHENTICATION_CONFIG + " system property. Google SignIn configuration file is: [" + filename + "]"); + try { + properties.load(new FileInputStream(filename)); + } catch (FileNotFoundException e) { + logger.error("Could not find file with Google Sign-In config: file [" + filename + "] not found"); + throw new SpagoBIRuntimeException("Could not find file with Google Sign-In config: file [" + filename + "] not found", e); + } catch (Exception e) { + logger.error("Could not read file with Google Sign-In config [" + filename + "]"); + throw new SpagoBIRuntimeException("Could not read file with Google Sign-In config [" + filename + "] not found", e); + } + String clientId = properties.getProperty(GOOGLE_CLIENT_ID); + logger.debug("Google Sign-In Client ID is [" + clientId + "]"); + Assert.assertNotBlank(clientId, "Google Sing-In Client ID was not found!"); + } + } catch (Exception e) { + logger.error("Error while loading Google Sing-In configuration file", e); + throw new SpagoBIRuntimeException("Error while loading Google Sing-In configuration file", e); + } + } + + public static boolean isEnabled() { + boolean toReturn = properties.containsKey(GOOGLE_CLIENT_ID); + LogMF.debug(logger, "Google Sign-In enabled: {0}", toReturn); + return toReturn; + } + + public static String getClientId() { + String toReturn = properties.getProperty(GOOGLE_CLIENT_ID); + LogMF.debug(logger, "Google Sign-In Client ID: {0}", toReturn); + return toReturn; + } + +} diff --git a/knowagejasperreportengine/src/main/webapp/META-INF/context.xml b/knowagejasperreportengine/src/main/webapp/META-INF/context.xml index ae33146db9e..da80a4a8802 100644 --- a/knowagejasperreportengine/src/main/webapp/META-INF/context.xml +++ b/knowagejasperreportengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/knowagekpiengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagekpiengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagekpiengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagekpiengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagekpiengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 5baa9837fc0..00000000000 --- a/knowagekpiengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagekpiengine/src/main/webapp/META-INF/context.xml b/knowagekpiengine/src/main/webapp/META-INF/context.xml index 90bcfa8d70b..61aadadcd92 100644 --- a/knowagekpiengine/src/main/webapp/META-INF/context.xml +++ b/knowagekpiengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/knowagekpiengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowagekpiengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index 55ba1bfcad3..f7d0d95fce7 100644 --- a/knowagekpiengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowagekpiengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -20,7 +20,7 @@ - +"> diff --git a/knowagekpiengine/src/main/webapp/js/angular_1.x/gaugeNgDirective/rLinearGauge/rLinearGauge.tpl.html b/knowagekpiengine/src/main/webapp/js/angular_1.x/gaugeNgDirective/rLinearGauge/rLinearGauge.tpl.html index fd82dc4dddb..c1a4e8b403a 100644 --- a/knowagekpiengine/src/main/webapp/js/angular_1.x/gaugeNgDirective/rLinearGauge/rLinearGauge.tpl.html +++ b/knowagekpiengine/src/main/webapp/js/angular_1.x/gaugeNgDirective/rLinearGauge/rLinearGauge.tpl.html @@ -1,4 +1,4 @@ -

+
{{min}}
{{threshold.to}}
diff --git a/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/LdapSecurityServiceSupplier.java b/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/LdapSecurityServiceSupplier.java index 379c1d04fce..579e1e0216a 100644 --- a/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/LdapSecurityServiceSupplier.java +++ b/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/LdapSecurityServiceSupplier.java @@ -21,12 +21,9 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; -import java.util.HashMap; import java.util.Hashtable; -import java.util.List; import java.util.Properties; import javax.naming.Context; @@ -35,11 +32,8 @@ import org.apache.log4j.Logger; -import it.eng.spago.error.EMFUserError; import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.metadata.SbiExtRoles; import it.eng.spagobi.profiling.bean.SbiUser; -import it.eng.spagobi.profiling.bean.SbiUserAttributes; import it.eng.spagobi.services.common.JWTSsoService; import it.eng.spagobi.services.security.bo.SpagoBIUserProfile; import it.eng.spagobi.services.security.service.ISecurityServiceSupplier; @@ -54,9 +48,9 @@ public class LdapSecurityServiceSupplier implements ISecurityServiceSupplier { static private Logger logger = Logger.getLogger(LdapSecurityServiceSupplier.class); - static private String LDAP_AUTHENTICATION_CONFIG = "ldap.config"; + static protected String LDAP_AUTHENTICATION_CONFIG = "ldap.config"; - private static int USER_JWT_TOKEN_EXPIRE_HOURS = 10; // JWT token for regular users will expire in 10 HOURS + protected static int USER_JWT_TOKEN_EXPIRE_HOURS = 10; // JWT token for regular users will expire in 10 HOURS @Override public SpagoBIUserProfile checkAuthentication(String userId, String psw) { @@ -65,8 +59,9 @@ public SpagoBIUserProfile checkAuthentication(String userId, String psw) { if (userId != null) { SbiUser user = DAOFactory.getSbiUserDAO().loadSbiUserByUserId(userId); if (user != null) { - if (!bind(userId, psw)) { - logger.error("Impossible to bind user " + userId + ". Usernmae or password password not valid."); + boolean bound = bind(userId, psw) != null; + if (!bound) { + logger.error("Impossible to bind user " + userId + ". Username or password not valid."); return null; } @@ -97,15 +92,14 @@ public SpagoBIUserProfile checkAuthentication(String userId, String psw) { /** * In this method you can find the authentication source code for LDAP bind process * - * @param userId: - * ex: CN=angelo,OU=ADAM USERS,O=Microsoft,C=US + * @param userId: ex: CN=angelo,OU=ADAM USERS,O=Microsoft,C=US * @param psw * @return * @throws IOException * @throws FileNotFoundException */ - protected boolean bind(String userId, String psw) throws FileNotFoundException, IOException { + protected InitialDirContext bind(String userId, String psw) throws FileNotFoundException, IOException { String filename = System.getProperty(LDAP_AUTHENTICATION_CONFIG); Assert.assertNotNull(filename, "System property " + LDAP_AUTHENTICATION_CONFIG + " has not been configured. Please add it while starting your JVM."); @@ -117,87 +111,36 @@ protected boolean bind(String userId, String psw) throws FileNotFoundException, env.put(Context.PROVIDER_URL, properties.getProperty("PROVIDER_URL")); env.put(Context.SECURITY_AUTHENTICATION, properties.getProperty("SECURITY_AUTHENTICATION")); - env.put(Context.SECURITY_PRINCIPAL, properties.getProperty("DN_PREFIX") + userId + properties.getProperty("DN_POSTFIX")); - logger.debug("User ID=" + properties.getProperty("DN_PREFIX") + userId + properties.getProperty("DN_POSTFIX")); - env.put(Context.SECURITY_CREDENTIALS, psw); - + if (userId != null) { + String distinguishName = null; + if (!userId.startsWith(properties.getProperty("DN_PREFIX")) && !userId.endsWith(properties.getProperty("DN_POSTFIX"))) { + distinguishName = properties.getProperty("DN_PREFIX") + userId + properties.getProperty("DN_POSTFIX"); + + logger.debug("User ID=" + properties.getProperty("DN_PREFIX") + userId + properties.getProperty("DN_POSTFIX")); + } else { + distinguishName = userId; + } + env.put(Context.SECURITY_PRINCIPAL, distinguishName); + env.put(Context.SECURITY_CREDENTIALS, psw); + } env.put("javax.security.sasl.qop", "auth-conf"); env.put("javax.security.sasl.strength", "high"); + InitialDirContext ctx = null; try { - new InitialDirContext(env); + ctx = new InitialDirContext(env); logger.debug("Authentication successfull."); - return true; + return ctx; } catch (NamingException e) { logger.error("Authentication NOT successfull. Reason: ", e); + return null; } - return false; } @Override - public SpagoBIUserProfile createUserProfile(String userId) { - logger.debug("IN: userId parameter is " + userId); - try { - SpagoBIUserProfile profile = getSpagoBIUserProfile(userId); - return profile; - } catch (Exception e) { - throw new SpagoBIRuntimeException("Error while creating user profile object", e); - } finally { - logger.debug("OUT"); - } - } - - public SpagoBIUserProfile getSpagoBIUserProfile(String userId) throws EMFUserError { - logger.debug("IN - userId: " + userId); - SpagoBIUserProfile profile = null; - SbiUser user = DAOFactory.getSbiUserDAO().loadSbiUserByUserId(userId); - - if (user == null) { - logger.error("UserName [" + userId + "] not found!!"); - return null; - } - - profile = new SpagoBIUserProfile(); - profile.setUniqueIdentifier(user.getUserId()); - profile.setUserId(user.getUserId()); - profile.setUserName(user.getFullName()); - profile.setOrganization(user.getCommonInfo().getOrganization()); - profile.setIsSuperadmin(user.getIsSuperadmin()); - - // get user name - String userName = userId; - - // get roles of the user - List assignedUserRoles = DAOFactory.getSbiUserDAO().loadSbiUserRolesById(user.getId()); - List roles = new ArrayList<>(); - - for (SbiExtRoles role : assignedUserRoles) { - roles.add(role.getName()); - } - - HashMap attributes = new HashMap<>(); - ArrayList assignedUserAttributes = DAOFactory.getSbiUserDAO().loadSbiUserAttributesById(user.getId()); - if (assignedUserAttributes != null) { - for (SbiUserAttributes attribute : assignedUserAttributes) { - String attributeName = attribute.getSbiAttribute().getAttributeName(); - String attributeValue = attribute.getAttributeValue(); - if (attributeValue != null) { - logger.debug("Add attribute. " + attributeName + "=" + attributeName + " to the user" + userName); - attributes.put(attributeName, attributeValue); - } - } - } - - logger.debug("Attributes load into Knowage user profile: " + attributes); - // end load profile attributes - - profile.setAttributes(attributes); - profile.setRoles(roles.toArray(new String[0])); - - logger.debug("OUT"); - return profile; - + public SpagoBIUserProfile createUserProfile(String jwtToken) { + return new InternalSecurityServiceSupplierImpl().createUserProfile(jwtToken); } @Override diff --git a/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/ProfiledLdapSecurityServiceSupplier.java b/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/ProfiledLdapSecurityServiceSupplier.java index c655fdbb9f1..441354b684b 100644 --- a/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/ProfiledLdapSecurityServiceSupplier.java +++ b/knowageldapsecurityprovider/src/main/java/it/eng/spagobi/security/ProfiledLdapSecurityServiceSupplier.java @@ -1,21 +1,45 @@ package it.eng.spagobi.security; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; import java.util.List; +import java.util.Properties; + +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; import org.apache.log4j.Logger; + import it.eng.spagobi.commons.dao.DAOFactory; import it.eng.spagobi.profiling.bean.SbiUser; import it.eng.spagobi.profiling.bean.SbiUserAttributes; +import it.eng.spagobi.services.common.JWTSsoService; import it.eng.spagobi.services.security.bo.SpagoBIUserProfile; +import it.eng.spagobi.utilities.assertion.Assert; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; public class ProfiledLdapSecurityServiceSupplier extends LdapSecurityServiceSupplier { + static private Logger logger = Logger.getLogger(ProfiledLdapSecurityServiceSupplier.class); + + private static final String SEARCH_USER_BEFORE_PSW = "SEARCH_USER_BEFORE_PSW"; + private static final String SEARCH_USER_BEFORE_USER = "SEARCH_USER_BEFORE_USER"; + private static final String SEARCH_USER_BEFORE = "SEARCH_USER_BEFORE"; + private static final String SEARCH_USER_BEFORE_FILTER = "SEARCH_USER_BEFORE_FILTER"; + private static final String ATTRIBUTE_AUTHENTICATION_MODE = "auth_mode"; private static final String ATTRIBUTE_AUTHENTICATION_MODE_LDAP = "LDAP"; private static final String ATTRIBUTE_AUTHENTICATION_MODE_INTERNAL = "internal"; @Override public SpagoBIUserProfile checkAuthentication(String userId, String psw) { + SbiUser user = DAOFactory.getSbiUserDAO().loadSbiUserByUserId(userId); if (user == null) { logger.error("UserName not found into database"); @@ -25,9 +49,117 @@ public SpagoBIUserProfile checkAuthentication(String userId, String psw) { if (ATTRIBUTE_AUTHENTICATION_MODE_INTERNAL.equals(authMode)) { return new InternalSecurityServiceSupplierImpl().checkAuthentication(userId, psw); } else { - return super.checkAuthentication(userId, psw); + /* NEW */ + String filename = System.getProperty(LDAP_AUTHENTICATION_CONFIG); + Assert.assertNotNull(filename, + "System property " + LDAP_AUTHENTICATION_CONFIG + " has not been configured. Please add it while starting your JVM."); + Properties properties = new Properties(); + + try { + properties.load(new FileInputStream(filename)); + } catch (FileNotFoundException e) { + logger.error("File properties [" + filename + "] not found"); + } catch (IOException e) { + logger.error("Impossible to read properties file [" + filename + "]"); + } + + Boolean searchUserBefore = new Boolean(properties.getProperty(SEARCH_USER_BEFORE)); + if (searchUserBefore) { + + String postfix = properties.getProperty("DN_POSTFIX"); + postfix = postfix.startsWith(",") ? postfix.substring(1) : postfix; + + String usernameForLDAPAuthBefore = new String(properties.getProperty(SEARCH_USER_BEFORE_USER)); + + boolean validUsername = usernameForLDAPAuthBefore != null && !usernameForLDAPAuthBefore.isEmpty(); + + String username = null; + String password = null; + if (validUsername) { + username = String.format("%s%s,%s", properties.getProperty("DN_PREFIX"), usernameForLDAPAuthBefore, postfix); + + String passwordForLDAPAuthBefore = new String(properties.getProperty(SEARCH_USER_BEFORE_PSW)); + password = passwordForLDAPAuthBefore; + logger.debug("Found credentials in properties file for authentication before looking for attribute."); + } + + InitialDirContext ctx; + String ldapCompleteNameAttribute = null; + try { + ctx = bind(username, password); + + String[] searchAttrs = { "nsRole", "uid", "objectClass", "givenName", "gn", "sn", "cn" }; + SearchControls ctrls = new SearchControls(); + ctrls.setSearchScope(SearchControls.SUBTREE_SCOPE); + ctrls.setCountLimit(0); + ctrls.setTimeLimit(0); + ctrls.setReturningAttributes(searchAttrs); + + String filter = String.format(properties.getProperty(SEARCH_USER_BEFORE_FILTER), userId); + + try { + NamingEnumeration answer = ctx.search(postfix, filter, ctrls); + + while (answer.hasMore()) { + SearchResult ldapResult = answer.next(); + // distinguish name + ldapCompleteNameAttribute = ldapResult.getNameInNamespace(); + break; + } + ctx.close(); + } catch (NamingException e) { + logger.error("Resource with given filters not found", e); + return null; + } + } catch (FileNotFoundException e) { + logger.error("File properties [" + filename + "] not found"); + } catch (IOException e) { + logger.error("Impossible to read properties file [" + filename + "]"); + } + + return checkAuthentication(userId, ldapCompleteNameAttribute, psw); + } else { + return super.checkAuthentication(userId, psw); + } } } + + } + + public SpagoBIUserProfile checkAuthentication(String userId, String ldapCompleteNameAttribute, String psw) { + SpagoBIUserProfile profile = null; + try { + if (userId != null) { + SbiUser user = DAOFactory.getSbiUserDAO().loadSbiUserByUserId(userId); + if (user != null) { + boolean bound = bind(ldapCompleteNameAttribute, psw) != null; + if (!bound) { + logger.error("Impossible to bind user " + userId + ". Username or password not valid."); + return null; + } + + profile = new SpagoBIUserProfile(); + + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.HOUR, USER_JWT_TOKEN_EXPIRE_HOURS); + Date expiresAt = calendar.getTime(); + + String jwtToken = JWTSsoService.userId2jwtToken(userId, expiresAt); + + profile.setUniqueIdentifier(jwtToken); + profile.setUserId(user.getUserId()); + profile.setUserName(user.getFullName()); + profile.setOrganization(user.getCommonInfo().getOrganization()); + profile.setIsSuperadmin(user.getIsSuperadmin()); + } else { + logger.error("UserName " + userId + " not found into database. Returning [null] as user profile"); + } + + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("Error while getting user profile object from database", e); + } + return profile; } private String getAuthMode(SbiUser user) { @@ -47,4 +179,5 @@ private String getAuthMode(SbiUser user) { public SpagoBIUserProfile createUserProfile(String jwtToken) { return new InternalSecurityServiceSupplierImpl().createUserProfile(jwtToken); } + } \ No newline at end of file diff --git a/knowageldapsecurityprovider/src/main/resources/it/eng/spagobi/security/ldap_authorizations.properties b/knowageldapsecurityprovider/src/main/resources/it/eng/spagobi/security/ldap_authorizations.properties index 3e99c9781b4..3c8e0b54ebd 100644 --- a/knowageldapsecurityprovider/src/main/resources/it/eng/spagobi/security/ldap_authorizations.properties +++ b/knowageldapsecurityprovider/src/main/resources/it/eng/spagobi/security/ldap_authorizations.properties @@ -1,5 +1,9 @@ -INITIAL_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory -PROVIDER_URL = ldap://localhost:389/ -SECURITY_AUTHENTICATION = simple -DN_PREFIX = CN= -DN_POSTFIX = ,OU=ADAM USERS,O=Microsoft,C=US \ No newline at end of file +INITIAL_CONTEXT_FACTORY = com.sun.jndi.ldap.LdapCtxFactory +PROVIDER_URL = ldaps://161.27.15.30:636 +SECURITY_AUTHENTICATION = simple +DN_PREFIX = CN= +DN_POSTFIX = ,ou=Persone,o=Engineering,c=IT +SEARCH_USER_BEFORE = true +SEARCH_USER_BEFORE_USER = +SEARCH_USER_BEFORE_PSW = +SEARCH_USER_BEFORE_FILTER = (&((objectclass=engPerson))(uid=%s)) \ No newline at end of file diff --git a/knowagemeta/src/main/java/it/eng/knowage/meta/service/MetaService.java b/knowagemeta/src/main/java/it/eng/knowage/meta/service/MetaService.java index d8ae3a7bf04..40165175291 100644 --- a/knowagemeta/src/main/java/it/eng/knowage/meta/service/MetaService.java +++ b/knowagemeta/src/main/java/it/eng/knowage/meta/service/MetaService.java @@ -214,6 +214,7 @@ public Response checkRelationships(@Context HttpServletRequest req) { EmfXmiSerializer serializer = new EmfXmiSerializer(); JSONObject jsonRoot = RestUtilities.readBodyAsJSONObject(req); Model model = (Model) req.getSession().getAttribute(EMF_MODEL); + setProfileDialectThreadLocal(model); JSONObject oldJsonModel = createJson(model); applyDiff(jsonRoot, model); @@ -442,6 +443,7 @@ public Response addBusinessView(@Context HttpServletRequest req) { try { JSONObject jsonRoot = RestUtilities.readBodyAsJSONObject(req); Model model = (Model) req.getSession().getAttribute(EMF_MODEL); + setProfileDialectThreadLocal(model); JSONObject oldJsonModel = createJson(model); applyDiff(jsonRoot, model); @@ -915,6 +917,7 @@ public Response deleteBusinessClass(@Context HttpServletRequest req) throws IOEx JSONObject jsonRoot = RestUtilities.readBodyAsJSONObject(req); Model model = (Model) req.getSession().getAttribute(EMF_MODEL); + setProfileDialectThreadLocal(model); JSONObject oldJsonModel = createJson(model); applyDiff(jsonRoot, model); @@ -979,6 +982,7 @@ public String deleteBusinessRelation(@Context HttpServletRequest req) throws IOE public Response deleteBusinessView(@Context HttpServletRequest req) throws IOException, JSONException, SpagoBIException { JSONObject jsonRoot = RestUtilities.readBodyAsJSONObject(req); Model model = (Model) req.getSession().getAttribute(EMF_MODEL); + setProfileDialectThreadLocal(model); JSONObject oldJsonModel = createJson(model); applyDiff(jsonRoot, model); @@ -1000,6 +1004,7 @@ public Response updatePhysicalModel(@Context HttpServletRequest req) throws ClassNotFoundException, NamingException, SQLException, JSONException, EMFUserError { PhysicalModelInitializer physicalModelInitializer = new PhysicalModelInitializer(); Model model = (Model) req.getSession().getAttribute(EMF_MODEL); + setProfileDialectThreadLocal(model); if (model.eAdapters().isEmpty()) model.eAdapters().add(new ECrossReferenceAdapter()); ECrossReferenceAdapter crossReferenceAdapter = (ECrossReferenceAdapter) model.eAdapters().get(0); // req.getSession().getAttribute(EMF_MODEL_CROSS_REFERENCE); @@ -1036,7 +1041,7 @@ public Response updatePhysicalModel(@Context HttpServletRequest req) public Response applyUpdatePhysicalModel(@Context HttpServletRequest req) throws ClassNotFoundException, NamingException, SQLException, JSONException, IOException, EMFUserError { Model model = (Model) req.getSession().getAttribute(EMF_MODEL); - + setProfileDialectThreadLocal(model); JSONObject oldJsonModel = createJson(model); String modelName = model.getName(); diff --git a/knowagemeta/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagemeta/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagemeta/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagemeta/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagemeta/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 5baa9837fc0..00000000000 --- a/knowagemeta/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache = new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config : allConfig) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: " + config.getLabel() +" / " + config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine", e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagemeta/src/main/webapp/META-INF/context.xml b/knowagemeta/src/main/webapp/META-INF/context.xml index acd76453948..0dd3911ace2 100644 --- a/knowagemeta/src/main/webapp/META-INF/context.xml +++ b/knowagemeta/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/knowagemeta/src/main/webapp/WEB-INF/jsp/metaWebTemplates/businessModelTab.jsp b/knowagemeta/src/main/webapp/WEB-INF/jsp/metaWebTemplates/businessModelTab.jsp index c023b66cfd3..b9147b55765 100644 --- a/knowagemeta/src/main/webapp/WEB-INF/jsp/metaWebTemplates/businessModelTab.jsp +++ b/knowagemeta/src/main/webapp/WEB-INF/jsp/metaWebTemplates/businessModelTab.jsp @@ -2,9 +2,17 @@ +
{{translate.load('sbi.meta.businessclass')}}
+
+ +
+ {{translate.load('sbi.meta.businessview')}} +
+
+ -
+ diff --git a/knowagemeta/src/main/webapp/js/src/meta/metaDefinitionController.js b/knowagemeta/src/main/webapp/js/src/meta/metaDefinitionController.js index 15f6b54c3b8..66dde3b978e 100644 --- a/knowagemeta/src/main/webapp/js/src/meta/metaDefinitionController.js +++ b/knowagemeta/src/main/webapp/js/src/meta/metaDefinitionController.js @@ -216,6 +216,7 @@ if(JSON.parse(response.data.patch).length>0){ metaModelServices.applyPatch(JSON.parse(response.data.patch)); $scope.$broadcast("updateBusinessClassesGrid"); + $scope.$broadcast("updateBusinessViewsGrid"); } sbiModule_restServices.promisePost("1.0/metaWeb", "generateModel", metaModelServices.createRequestRest(dataToSend)) .then( diff --git a/knowagemeta/src/main/webapp/js/src/meta/metaModelCreationController.js b/knowagemeta/src/main/webapp/js/src/meta/metaModelCreationController.js index 3917f2f4cc1..7e6fcebfc98 100644 --- a/knowagemeta/src/main/webapp/js/src/meta/metaModelCreationController.js +++ b/knowagemeta/src/main/webapp/js/src/meta/metaModelCreationController.js @@ -212,10 +212,42 @@ function metaModelCreationBusinessControllerFunction($scope, sbiModule_translate rowData : $scope.meta.businessModels }; + //Ag-grid table business view + $scope.businessViewsGrid = { + angularCompileRows: true, + domLayout: 'autoHeight', + enableColResize: false, + enableSorting: false, + enableFilter: false, + rowDragManaged: true, + headerHeight: 0, + onRowDragEnter: rowDragEnter, + onRowDragEnd: onRowDragEnd, + onGridReady: resizeColumns, + onGridSizeChanged: resizeColumns, + rowSelection: 'single', + onRowClicked: rowSelection, + columnDefs: [{"headerName":sbiModule_translate.load("sbi.generic.name"),"field":"name",rowDrag: true,cellRenderer: fullWidthRow }], + rowData : $scope.meta.businessViews + }; + $scope.$on('updateBusinessClassesGrid',function(event,data){ $scope.businessClassesGrid.api.setRowData($scope.meta.businessModels); }) + $scope.$on('updateBusinessViewsGrid',function(event,data){ + if($scope.businessViewsGrid.api) { + $scope.businessViewsGrid.api.setRowData($scope.meta.businessViews); + } + }) + + $scope.$watch('selectedBusinessModel.name',function(newValue,oldValue){ + if($scope.selectedBusinessModel && newValue!=oldValue){ + $scope.businessClassesGrid.api.setRowData($scope.meta.businessModels); + $scope.businessViewsGrid.api.setRowData($scope.meta.businessViews); + } + + },true) function moveInArray(arr, fromIndex, toIndex) { var element = arr[fromIndex]; @@ -329,13 +361,13 @@ function metaModelCreationBusinessControllerFunction($scope, sbiModule_translate $mdDialog.show({ controller: addBusinessViewController, preserveScope: true, - locals: { originalPhysicalModel: $scope.meta.physicalModels,selectedBusinessModel: $scope.selectedBusinessModel,editMode:editMode}, + locals: { originalPhysicalModel: $scope.meta.physicalModels,selectedBusinessModel: $scope.selectedBusinessModel,editMode:editMode, businessViewsGrid: $scope.businessViewsGrid}, templateUrl:sbiModule_config.contextName + '/js/src/meta/templates/addBusinessView.jsp', clickOutsideToClose:false, escapeToClose :false, fullscreen: true }).then(function(){ - $scope.businessViewTreeInterceptor.refreshTree(); + $scope.businessViewsGrid.api.setRowData($scope.meta.businessViews); }); }; @@ -353,6 +385,7 @@ function metaModelCreationBusinessControllerFunction($scope, sbiModule_translate .then(function(response){ metaModelServices.applyPatch(response.data); $scope.businessClassesGrid.api.setRowData($scope.meta.businessModels); + $scope.businessViewsGrid.api.setRowData($scope.meta.businessViews); $scope.selectedBusinessModel=undefined; },function(response){ sbiModule_restServices.errorHandler(response.data,sbiModule_translate.load("sbi.generic.genericError")); @@ -514,7 +547,6 @@ function businessModelAttributeControllerFunction($scope, $timeout,$mdDialog, sb onGridSizeChanged: resizeColumns, onCellEditingStopped: refreshRow, singleClickEdit: true, - stopEditingWhenGridLosesFocus: true, domLayout: "autoHeight", columnDefs: [{"headerName":sbiModule_translate.load("sbi.generic.name"),"field":"name",rowDrag: true, "editable":true,cellRenderer:editableCellWithIcon, cellClass: 'editableCell',width: 90}, {"headerName":sbiModule_translate.load("sbi.meta.model.table.primaryKey"),"field":"identifier",cellRenderer:checkboxRenderer,width: 40}, @@ -611,7 +643,11 @@ function businessModelAttributeControllerFunction($scope, $timeout,$mdDialog, sb } $scope.toggleAttributeVisibility = function(index){ - $scope.selectedBusinessModel.columns[index].properties[0]['structural.visible']['value'] = !$scope.selectedBusinessModel.columns[index].properties[0]['structural.visible']['value']; + if($scope.selectedBusinessModel.columns[index].properties[0]['structural.visible']['value']=='true'){ + $scope.selectedBusinessModel.columns[index].properties[0]['structural.visible']['value'] = false; + } else { + $scope.selectedBusinessModel.columns[index].properties[0]['structural.visible']['value'] = true; + } } $scope.openDetails = function(index, ev){ @@ -638,7 +674,7 @@ function businessModelAttributeControllerFunction($scope, $timeout,$mdDialog, sb $scope.translate=sbiModule_translate; $scope.physicalColumn = attribute.physicalColumn; $scope.sbiModule_config = sbiModule_config; - $scope.selectedAttribute = angular.copy(attribute); + $scope.selectedAttribute = attribute; var utilityMap = []; $scope.properties = {}; for(var k in $scope.selectedAttribute.properties){ @@ -665,6 +701,16 @@ function businessModelAttributeControllerFunction($scope, $timeout,$mdDialog, sb $mdDialog.hide($scope.selectedAttribute); } + $scope.initRoleVisibility=function(rv,val){ + if(!angular.equals("",val)){ + angular.copy(val.split(";"),rv ); + } + } + + $scope.buildRoleVisibility=function(rv,val){ + val.value=rv.join(";"); + } + $scope.delete = function(selectedAttribute){ console.log("deleting field") deleteBusinessColumn(selectedAttribute.uniqueName,selectedBusinessModel) diff --git a/knowagemeta/src/main/webapp/js/src/meta/templates/attributesDialogTemplate.html b/knowagemeta/src/main/webapp/js/src/meta/templates/attributesDialogTemplate.html index 62ccb811889..364f169adc2 100644 --- a/knowagemeta/src/main/webapp/js/src/meta/templates/attributesDialogTemplate.html +++ b/knowagemeta/src/main/webapp/js/src/meta/templates/attributesDialogTemplate.html @@ -50,7 +50,9 @@

{{translate.load('sbi.glossary.attributedetail')}}

- + {{option}} @@ -60,6 +62,7 @@

{{translate.load('sbi.glossary.attributedetail')}}

+ {{option}} diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/exporter/QbeXLSExporter.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/exporter/QbeXLSExporter.java index f571ccb48b8..1f808121ede 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/exporter/QbeXLSExporter.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/exporter/QbeXLSExporter.java @@ -17,15 +17,6 @@ */ package it.eng.spagobi.engines.qbe.exporter; -import it.eng.spagobi.engines.qbe.bo.MeasureScaleFactorOption; -import it.eng.spagobi.engines.qbe.query.Field; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.common.datastore.IField; -import it.eng.spagobi.tools.dataset.common.datastore.IRecord; -import it.eng.spagobi.tools.dataset.common.metadata.IFieldMetaData; -import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; -import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; - import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -48,6 +39,15 @@ import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; +import it.eng.spagobi.engines.qbe.bo.MeasureScaleFactorOption; +import it.eng.spagobi.engines.qbe.query.Field; +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; +import it.eng.spagobi.tools.dataset.common.datastore.IField; +import it.eng.spagobi.tools.dataset.common.datastore.IRecord; +import it.eng.spagobi.tools.dataset.common.metadata.IFieldMetaData; +import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + public class QbeXLSExporter { /** Logger component. */ @@ -117,27 +117,41 @@ public Object getProperty(String propertyName) { return this.properties.get(propertyName); } - public Workbook export() { + public Workbook export(String exportLimit, boolean showLimitExportMessage) { Workbook workbook = this.instantiateWorkbook(); CreationHelper createHelper = workbook.getCreationHelper(); Sheet sheet = workbook.createSheet("new sheet"); for (int j = 0; j < 50; j++) { sheet.createRow(j); } - fillSheet(sheet, workbook, createHelper, 0); + fillSheet(sheet, workbook, createHelper, 0, exportLimit, showLimitExportMessage); return workbook; } - public void fillSheet(Sheet sheet, Workbook wb, CreationHelper createHelper, int startRow) { + public void fillSheet(Sheet sheet, Workbook wb, CreationHelper createHelper, int startRow, String exportLimit, boolean showLimitExportMessage) { // we enrich the JSON object putting every node the descendants_no // property: it is useful when merging cell into rows/columns headers // and when initializing the sheet if (dataStore != null && !dataStore.isEmpty()) { + if (showLimitExportMessage) { + fillMessageHeader(sheet, exportLimit); + startRow = 1; + } CellStyle[] cellTypes = fillSheetHeader(sheet, wb, createHelper, startRow, DEFAULT_START_COLUMN); fillSheetData(sheet, wb, createHelper, cellTypes, startRow + 1, DEFAULT_START_COLUMN); } } + private void fillMessageHeader(Sheet sheet, String exportLimit) { + int beginRowMessageData = 0; + String message = "Query results are exceeding configured threshold, therefore only " + exportLimit + " were exported."; + CellStyle messageCellStyle = buildHeaderCellStyle(sheet); + Row messageRow = sheet.getRow(beginRowMessageData); + Cell cell = messageRow.createCell(0); + cell.setCellValue(message); + cell.setCellStyle(messageCellStyle); + } + /** * * @param sheet @@ -222,8 +236,8 @@ public CellStyle buildHeaderCellStyle(Sheet sheet) { String headerBGColor = (String) this.getProperty(PROPERTY_HEADER_BACKGROUND_COLOR); logger.debug("Header background color : " + headerBGColor); - short backgroundColorIndex = headerBGColor != null ? IndexedColors.valueOf(headerBGColor).getIndex() : IndexedColors.valueOf( - DEFAULT_HEADER_BACKGROUND_COLOR).getIndex(); + short backgroundColorIndex = headerBGColor != null ? IndexedColors.valueOf(headerBGColor).getIndex() + : IndexedColors.valueOf(DEFAULT_HEADER_BACKGROUND_COLOR).getIndex(); cellStyle.setFillForegroundColor(backgroundColorIndex); cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); @@ -235,8 +249,8 @@ public CellStyle buildHeaderCellStyle(Sheet sheet) { String bordeBorderColor = (String) this.getProperty(PROPERTY_HEADER_BORDER_COLOR); logger.debug("Header border color : " + bordeBorderColor); - short borderColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(bordeBorderColor).getIndex() : IndexedColors.valueOf( - DEFAULT_HEADER_BORDER_COLOR).getIndex(); + short borderColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(bordeBorderColor).getIndex() + : IndexedColors.valueOf(DEFAULT_HEADER_BORDER_COLOR).getIndex(); cellStyle.setLeftBorderColor(borderColorIndex); cellStyle.setRightBorderColor(borderColorIndex); @@ -257,8 +271,8 @@ public CellStyle buildHeaderCellStyle(Sheet sheet) { String headerColor = (String) this.getProperty(PROPERTY_HEADER_COLOR); logger.debug("Header color : " + headerColor); - short headerColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(headerColor).getIndex() : IndexedColors.valueOf(DEFAULT_HEADER_COLOR) - .getIndex(); + short headerColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(headerColor).getIndex() + : IndexedColors.valueOf(DEFAULT_HEADER_COLOR).getIndex(); font.setColor(headerColorIndex); font.setBoldweight(Font.BOLDWEIGHT_BOLD); @@ -274,8 +288,8 @@ public CellStyle buildCellStyle(Sheet sheet) { String cellBGColor = (String) this.getProperty(PROPERTY_CELL_BACKGROUND_COLOR); logger.debug("Cell background color : " + cellBGColor); - short backgroundColorIndex = cellBGColor != null ? IndexedColors.valueOf(cellBGColor).getIndex() : IndexedColors.valueOf(DEFAULT_CELL_BACKGROUND_COLOR) - .getIndex(); + short backgroundColorIndex = cellBGColor != null ? IndexedColors.valueOf(cellBGColor).getIndex() + : IndexedColors.valueOf(DEFAULT_CELL_BACKGROUND_COLOR).getIndex(); cellStyle.setFillForegroundColor(backgroundColorIndex); cellStyle.setFillPattern(CellStyle.SOLID_FOREGROUND); @@ -287,8 +301,8 @@ public CellStyle buildCellStyle(Sheet sheet) { String bordeBorderColor = (String) this.getProperty(PROPERTY_CELL_BORDER_COLOR); logger.debug("Cell border color : " + bordeBorderColor); - short borderColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(bordeBorderColor).getIndex() : IndexedColors.valueOf( - DEFAULT_CELL_BORDER_COLOR).getIndex(); + short borderColorIndex = bordeBorderColor != null ? IndexedColors.valueOf(bordeBorderColor).getIndex() + : IndexedColors.valueOf(DEFAULT_CELL_BORDER_COLOR).getIndex(); cellStyle.setLeftBorderColor(borderColorIndex); cellStyle.setRightBorderColor(borderColorIndex); diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/registry/serializer/RegistryJSONDataWriter.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/registry/serializer/RegistryJSONDataWriter.java index 4f7b49b5156..74bc5ea4477 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/registry/serializer/RegistryJSONDataWriter.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/registry/serializer/RegistryJSONDataWriter.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -26,21 +26,21 @@ public class RegistryJSONDataWriter extends JSONDataWriter { @Override -// protected String getFieldName(IFieldMetaData fieldMetaData, int i) { -// return super.getFieldHeader(fieldMetaData, i); -// } - + // protected String getFieldName(IFieldMetaData fieldMetaData, int i) { + // return super.getFieldHeader(fieldMetaData, i); + // } protected String getFieldName(IFieldMetaData fieldMetaData, int i) { - //String fieldName = "column_" + (i+1); - String pathName = fieldMetaData.getName(); + String fieldName = "column_" + (i + 1); // extract field name - int index = pathName.lastIndexOf(':'); - - String fieldName = pathName.substring(index+1); - + return fieldName; } - -} + @Override + protected String getFieldHeader(IFieldMetaData fieldMetaData) { + String fieldHeader = fieldMetaData.getName(); + return fieldHeader; + } + +} diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/ExportResultAction.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/ExportResultAction.java index 537bb1cc1d8..6328fd7ad35 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/ExportResultAction.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/ExportResultAction.java @@ -80,6 +80,7 @@ public class ExportResultAction extends AbstractQbeEngineAction { public static final String QUERY = "query"; public static final String RESPONSE_TYPE = "RESPONSE_TYPE"; public static final String PARS = "pars"; + public static final String LIMIT = "limit"; // misc public static final String RESPONSE_TYPE_INLINE = "RESPONSE_TYPE_INLINE"; @@ -96,6 +97,7 @@ public void service(SourceBean request, SourceBean response) { String responseType = null; boolean writeBackResponseInline = false; String mimeType = null; + String exportLimit = null; JSONObject queryJSON = null; String fileExtension = null; IStatement statement = null; @@ -122,6 +124,9 @@ public void service(SourceBean request, SourceBean response) { mimeType = getAttributeAsString(MIME_TYPE); logger.debug(MIME_TYPE + ": " + mimeType); + exportLimit = getAttributeAsString(LIMIT); + logger.debug(LIMIT + ": " + exportLimit); + responseType = getAttributeAsString(RESPONSE_TYPE); logger.debug(RESPONSE_TYPE + ": " + responseType); @@ -202,11 +207,11 @@ public void service(SourceBean request, SourceBean response) { if ("application/vnd.ms-excel".equalsIgnoreCase(mimeType)) { // export into XLS - exportIntoXLS(writeBackResponseInline, mimeType, statement, sqlQuery, extractedFields); + exportIntoXLS(writeBackResponseInline, mimeType, statement, sqlQuery, extractedFields, exportLimit); } else if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equalsIgnoreCase(mimeType)) { // export into XLSX - exportIntoXLSX(writeBackResponseInline, mimeType, statement, sqlQuery, extractedFields); + exportIntoXLSX(writeBackResponseInline, mimeType, statement, sqlQuery, extractedFields, exportLimit); } else if ("text/csv".equalsIgnoreCase(mimeType)) { // export into CSV @@ -281,14 +286,28 @@ private void exportIntoCSV(boolean writeBackResponseInline, String mimeType, Str } } - private void exportIntoXLS(boolean writeBackResponseInline, String mimeType, IStatement statement, String sqlQuery, Vector extractedFields) - throws EMFInternalError, IOException, FileNotFoundException, SpagoBIEngineException { - IDataStore dataStore = getDataStore(statement, sqlQuery); + private int getResultNumber(IDataStore dataStore) { + int resultNumber; + Object propertyRawValue; + propertyRawValue = dataStore.getMetaData().getProperty("resultNumber"); + resultNumber = ((Integer) propertyRawValue).intValue(); + return resultNumber; + } + + private void exportIntoXLS(boolean writeBackResponseInline, String mimeType, IStatement statement, String sqlQuery, Vector extractedFields, + String exportLimit) throws EMFInternalError, IOException, FileNotFoundException, SpagoBIEngineException { + IDataStore dataStore = getDataStore(statement, sqlQuery, exportLimit); Locale locale = (Locale) getEngineInstance().getEnv().get(EngineConstants.ENV_LOCALE); QbeXLSExporter exp = new QbeXLSExporter(dataStore, locale); exp.setExtractedFields(extractedFields); - Workbook wb = exp.export(); + int resultNumber = getResultNumber(dataStore); + Integer limit = parseExportLimit(exportLimit); + boolean showLimitExportMessage = false; + if (resultNumber > limit) { + showLimitExportMessage = true; + } + Workbook wb = exp.export(exportLimit, showLimitExportMessage); File file = File.createTempFile("workbook", ".xls"); FileOutputStream stream = new FileOutputStream(file); @@ -310,15 +329,20 @@ private void exportIntoXLS(boolean writeBackResponseInline, String mimeType, ISt } } - private void exportIntoXLSX(boolean writeBackResponseInline, String mimeType, IStatement statement, String sqlQuery, Vector extractedFields) - throws EMFInternalError, IOException, FileNotFoundException, SpagoBIEngineException { - IDataStore dataStore = getDataStore(statement, sqlQuery); - + private void exportIntoXLSX(boolean writeBackResponseInline, String mimeType, IStatement statement, String sqlQuery, Vector extractedFields, + String exportLimit) throws EMFInternalError, IOException, FileNotFoundException, SpagoBIEngineException { + IDataStore dataStore = getDataStore(statement, sqlQuery, exportLimit); Locale locale = (Locale) getEngineInstance().getEnv().get(EngineConstants.ENV_LOCALE); QbeXLSXExporter exp = new QbeXLSXExporter(dataStore, locale); exp.setExtractedFields(extractedFields); - Workbook wb = exp.export(); + int resultNumber = getResultNumber(dataStore); + Integer limit = parseExportLimit(exportLimit); + boolean showLimitExportMessage = false; + if (resultNumber > limit) { + showLimitExportMessage = true; + } + Workbook wb = exp.export(exportLimit, showLimitExportMessage); File file = File.createTempFile("workbook", ".xlsx"); FileOutputStream stream = new FileOutputStream(file); @@ -340,7 +364,7 @@ private void exportIntoXLSX(boolean writeBackResponseInline, String mimeType, IS } } - private IDataStore getDataStore(IStatement statement, String sqlQuery) throws EMFInternalError { + private IDataStore getDataStore(IStatement statement, String sqlQuery, String exportLimit) throws EMFInternalError { IDataStore dataStore = null; boolean isFormEngineInstance = getEngineInstance().getTemplate().getProperty("formJSONTemplate") != null; @@ -349,7 +373,8 @@ private IDataStore getDataStore(IStatement statement, String sqlQuery) throws EM IDataSet dataSet = null; - Integer limit = 0; + Integer limit = parseExportLimit(exportLimit); + Integer start = 0; Integer maxSize = QbeEngineConfig.getInstance().getResultLimit(); boolean isMaxResultsLimitBlocking = QbeEngineConfig.getInstance().isMaxResultLimitBlocking(); @@ -391,6 +416,18 @@ private IDataStore getDataStore(IStatement statement, String sqlQuery) throws EM return dataStore; } + private Integer parseExportLimit(String exportLimit) { + Integer limit; + try { + limit = Integer.parseInt(exportLimit); + } catch (NumberFormatException e) { + String msg = "Export limit cannot be parsed, check if value set for dataset.export.xls.resultsLimit in Configuration Management is numeric"; + logger.error(msg, e); + limit = 10000; + } + return limit; + } + private void decorateExtractedFields(List extractedFields, Query query) { List selectedFields = query.getSelectFields(true); Iterator selectedFieldsIterator = selectedFields.iterator(); diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/GetFilterValuesAction.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/GetFilterValuesAction.java index c25ce12da97..58bbc75502d 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/GetFilterValuesAction.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/core/GetFilterValuesAction.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,12 +11,25 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.engines.qbe.services.core; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.json.JSONException; +import org.json.JSONObject; + +import com.jamonapi.Monitor; +import com.jamonapi.MonitorFactory; + import it.eng.qbe.datasource.IDataSource; import it.eng.qbe.model.structure.IModelEntity; import it.eng.qbe.model.structure.IModelField; @@ -42,19 +55,6 @@ import it.eng.spagobi.utilities.engines.SpagoBIEngineServiceExceptionHandler; import it.eng.spagobi.utilities.service.JSONSuccess; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.log4j.Logger; -import org.json.JSONException; -import org.json.JSONObject; - -import com.jamonapi.Monitor; -import com.jamonapi.MonitorFactory; - /** * @authors Davide Zerbetto (davide.zerbetto@eng.it) Andrea Gioia (andrea.gioia@eng.it) */ @@ -195,8 +195,8 @@ public void service(SourceBean request, SourceBean response) { logger.debug("Query executed succesfully"); resultNumber = (Integer) dataStore.getMetaData().getProperty("resultNumber"); - Assert.assertNotNull(resultNumber, "property [resultNumber] of the dataStore returned by loadData method of the class [" - + dataSet.getClass().getName() + "] cannot be null"); + Assert.assertNotNull(resultNumber, + "property [resultNumber] of the dataStore returned by loadData method of the class [" + dataSet.getClass().getName() + "] cannot be null"); logger.debug("Total records: " + resultNumber); dataSetWriter = new JSONDataWriter(); @@ -287,6 +287,27 @@ private Query buildQuery(String entityId, String orderEntity, String orderType, for (int i = 0; i < lstDependences.length; i++) { String nameFiledWhere = lstDependences[i].substring(0, lstDependences[i].indexOf("=")); String valueFieldWhere = lstDependences[i].substring(lstDependences[i].indexOf("=") + 1); + + if (queryRootEntity) { + IDataSource model = getDataSource(); + IModelStructure structure = model.getModelStructure(); + IModelField selectField = structure.getField(nameFiledWhere); + IModelEntity parentEntity = selectField.getParent(); + logger.debug("Parent entity is " + parentEntity.getUniqueName()); + IModelEntity rootEntity = structure.getRootEntity(parentEntity); + logger.debug("Relevant root entity is " + rootEntity.getUniqueName()); + List fields = rootEntity.getAllFields(); + Iterator it = fields.iterator(); + String dependencyEntityId = null; + while (it.hasNext()) { + IModelField aField = (IModelField) it.next(); + if (aField.getName().equals(selectField.getName())) { + dependencyEntityId = aField.getUniqueName(); + break; + } + } + nameFiledWhere = dependencyEntityId; + } String[] fields = new String[] { nameFiledWhere }; String[] values = new String[] { valueFieldWhere }; WhereField.Operand left = new WhereField.Operand(fields, "name", AbstractStatement.OPERAND_TYPE_SIMPLE_FIELD, null, null); diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/LoadRegistryAction.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/LoadRegistryAction.java index dc003ff2057..ff0657663ca 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/LoadRegistryAction.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/LoadRegistryAction.java @@ -671,7 +671,8 @@ private Query buildQuery() { ? column.getSorter().toUpperCase() : null; - query.addSelectFiled(field.getUniqueName(), "NONE", field.getName(), true, true, false, sorter, field.getPropertyAsString("format")); + query.addSelectFiled(field.getUniqueName(), "NONE", field.getName(), true, true, false, sorter, field.getPropertyAsString("format"), null, + field.getJavaClass()); fieldNameIdMap.put(column.getField(), field.getUniqueName()); } } diff --git a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/UpdateRecordsAction.java b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/UpdateRecordsAction.java index db73b73583f..4acb3e4a0ab 100644 --- a/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/UpdateRecordsAction.java +++ b/knowageqbeengine/src/main/java/it/eng/spagobi/engines/qbe/services/registry/UpdateRecordsAction.java @@ -139,7 +139,9 @@ private Vector executeUpdate() throws Exception { IDataSource genericDatasource = qbeEngineInstance.getDataSource(); keyColumn = genericDatasource.getPersistenceManager().getKeyColumn(aRecord, registryConf); - Object keyValueObject = aRecord.get(keyColumn); + Object keyValueObject = null; + if (aRecord.has(keyColumn)) + keyValueObject = aRecord.get(keyColumn); if (keyValueObject == null || keyValueObject.toString().equalsIgnoreCase("")) { logger.debug("Insert a new Row"); diff --git a/knowageqbeengine/src/main/webapp/META-INF/context.xml b/knowageqbeengine/src/main/webapp/META-INF/context.xml index 05306eac05a..095ee1c4d45 100644 --- a/knowageqbeengine/src/main/webapp/META-INF/context.xml +++ b/knowageqbeengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index a60262c0f15..e5034c9375a 100644 --- a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -38,8 +38,6 @@ along with this program. If not, see . "> "> - - diff --git a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/formulas/formulaService.jspf b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/formulas/formulaService.jspf index f6f97a2e2e0..eb8e57df823 100644 --- a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/formulas/formulaService.jspf +++ b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/formulas/formulaService.jspf @@ -53,7 +53,7 @@ angular.module('formulas') getCustomFormulas: function(){ sbiModule_restServices.alterContextPath(sbiModule_config.externalBasePath); return sbiModule_restServices.promiseGet("2.0/configs","KNOWAGE.CUSTOMIZED_DATABASE_FUNCTIONS/"+dataSourceId); - } + } }; }); diff --git a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/sbiModule/sbiModuleConfig.jspf b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/sbiModule/sbiModuleConfig.jspf index 19e20d45d29..20fbdfe21b7 100644 --- a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/sbiModule/sbiModuleConfig.jspf +++ b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/commons/angular/sbiModule/sbiModuleConfig.jspf @@ -23,6 +23,8 @@ angular.module('sbiModule') protocol: '<%= request.getScheme()%>' , host: '<%= request.getServerName()%>', port: '<%= request.getServerPort()%>', + curr_country: '<%=locale.getCountry()%>', + curr_language: '<%=locale.getLanguage()%>', contextName: '/<%= request.getContextPath().startsWith("/")||request.getContextPath().startsWith("\\")?request.getContextPath().substring(1): request.getContextPath()%>', externalBasePath:"<%=request.getParameter(SpagoBIConstants.SBI_CONTEXT)%>", sbiExecutionID:'<%=request.getParameter(SpagoBIConstants.SBI_EXECUTION_ID)%>', diff --git a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/qbe.jsp b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/qbe.jsp index 84479477cc0..59ab0d3935c 100644 --- a/knowageqbeengine/src/main/webapp/WEB-INF/jsp/qbe.jsp +++ b/knowageqbeengine/src/main/webapp/WEB-INF/jsp/qbe.jsp @@ -29,7 +29,7 @@ along with this program. If not, see .
-
+
. -<%@include file="/WEB-INF/jsp/registry/registryConfig/registryConfigModule.jspf"%> -"> \ No newline at end of file +<%@include file="/WEB-INF/jsp/registry/registryConfig/registryConfigModule.jspf"%> \ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/common/export/services/exportService.js b/knowageqbeengine/src/main/webapp/js/src/qbe/common/export/services/exportService.js index eef4c7bf2c2..60632dbd5cc 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/common/export/services/exportService.js +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/common/export/services/exportService.js @@ -26,7 +26,7 @@ exporters.push(new Exporter('xlsx','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')); var query = {}; var bodySend = {}; - + var exportLimit = ''; return { @@ -53,6 +53,7 @@ exportResultAction.formParams.query = query; exportResultAction.formParams.pars = bodySend.pars; exportResultAction.conf.responseType = 'arraybuffer'; + exportResultAction.queryParams.limit = exportLimit; exportResultAction.executeAction().then(function(response){ sbiModuleDownloadService.getBlob(response); @@ -75,7 +76,14 @@ }, setBody : function (b) { bodySend = b; - } + }, + setExportLimit : function (el) { + exportLimit = el; + }, + getExportLimitation: function(){ + sbiModule_restServices.alterContextPath(sbiModule_config.externalBasePath); + return sbiModule_restServices.promiseGet("2.0/configs","EXPORT.LIMITATION"); + } } }) diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/controller/controller.js b/knowageqbeengine/src/main/webapp/js/src/qbe/controller/controller.js index 1add4b0c726..09c7ebeacdc 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/controller/controller.js +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/controller/controller.js @@ -91,6 +91,9 @@ function qbeFunction($scope,$rootScope,$filter,entity_service,query_service,filt $scope.fromDataset = true $scope.editQueryObj = qbeJsonObj.catalogue.queries[0]; } + if(message.smartView != undefined) { + query_service.smartView = message.smartView; + } console.log(message) } @@ -107,6 +110,13 @@ function qbeFunction($scope,$rootScope,$filter,entity_service,query_service,filt } Array.prototype.push.apply($scope.formulas, $scope.customTransformedFormulas); }); + + exportService.getExportLimitation().then(function(response) { + if(response.data){ + exportService.setExportLimit(response.data); + }; + }); + var queryHandler = function(newCatalogue,oldCatalogue){ $scope.meta.length = 0; exportService.setQuery(newCatalogue); @@ -132,7 +142,11 @@ function qbeFunction($scope,$rootScope,$filter,entity_service,query_service,filt query_service.count++; var finalPromise = $scope.executeQuery($scope.editQueryObj, $scope.bodySend, $scope.queryModel, false); if(finalPromise) { - finalPromise.then(function(){},function(){ + finalPromise.then(function(response){ + $scope.addToQueryModelWithoutExecutingQuery($scope.editQueryObj, $scope.queryModel); + exportService.setBody($scope.bodySend); + window.parent.queryCatalogue = {catalogue: {queries: [$scope.editQueryObj]}}; + },function(){ angular.copy(oldCatalogue,$scope.editQueryObj); for(var i in $scope.previousVersionRelations){ var relationship = $scope.previousVersionRelations[i] @@ -145,15 +159,18 @@ function qbeFunction($scope,$rootScope,$filter,entity_service,query_service,filt $rootScope.$emit('smartView'); query_service.count = 0; } - - }); + }else{ + $scope.addToQueryModelWithoutExecutingQuery($scope.editQueryObj, $scope.queryModel); + exportService.setBody($scope.bodySend); + window.parent.queryCatalogue = {catalogue: {queries: [$scope.editQueryObj]}}; } } else { $scope.addToQueryModelWithoutExecutingQuery($scope.editQueryObj, $scope.queryModel); + exportService.setBody($scope.bodySend); + window.parent.queryCatalogue = {catalogue: {queries: [$scope.editQueryObj]}}; } - exportService.setBody($scope.bodySend); - window.parent.queryCatalogue = {catalogue: {queries: [$scope.editQueryObj]}}; + } $scope.$watch('bodySend',function(newValue,oldValue){ @@ -224,14 +241,13 @@ function qbeFunction($scope,$rootScope,$filter,entity_service,query_service,filt if(query.fields.length>0){ queryModel.length = 0; for (var i = 0; i < query.fields.length; i++) { - var key = "column_"+(i+1); var queryObject = { "id":query.fields[i].id, + "key": "column_" + (i+1), "name":query.fields[i].field, "alias":query.fields[i].alias, "entity":query.fields[i].entity, "color":query.fields[i].color, - "data":[], "type":query.fields[i].type, "funct":query.fields[i].funct, "fieldType" : query.fields[i].fieldType, diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table-header.html b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table-header.html new file mode 100755 index 00000000000..8f61bd913a2 --- /dev/null +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table-header.html @@ -0,0 +1,86 @@ +
+ +
+ {{field.name}} + +

+ {{field.alias}} + {{field.alias}} +

+ + + {{::translate.load("kn.qbe.custom.table.column.settings")}} + + {{::translate.load("kn.qbe.custom.table.show.field")}} + + {{::translate.load("kn.qbe.selectgridpanel.name.temporalOperand.parameter")}} + + {{::translate.load("kn.qbe.custom.table.function.temporal")}} + + + YTD + LAST_YEAR + PARALLEL_YEAR MTD + + LAST_MONTH + + {{::translate.load("kn.qbe.custom.table.group")}} + {{::translate.load("kn.qbe.custom.table.aggregation")}} + + {{::translate.load("kn.qbe.custom.table.none")}} + {{::translate.load("kn.qbe.custom.table.sum")}} + {{::translate.load("kn.qbe.custom.table.min")}} + {{::translate.load("kn.qbe.custom.table.max")}} + {{::translate.load("kn.qbe.custom.table.avg")}} + {{::translate.load("kn.qbe.custom.table.count")}} + {{::translate.load("kn.qbe.custom.table.count.distinct")}} + {{::translate.load("kn.qbe.custom.table.move.left")}} + {{::translate.load("kn.qbe.custom.table.move.right")}} + + {{::translate.load("kn.qbe.general.alias")}} + {{::translate.load("kn.qbe.custom.table.delete.column")}} + +
+
+ +
\ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table.html b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table.html index 179764af1f6..dff45ede735 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table.html +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/custom-table.html @@ -1,34 +1,39 @@
-
- - - - - - {{::translate.load("kn.qbe.selectgridpanel.buttons.tt.deleteall")}} - - - +
+ + Hide List + Show List + + + + + + + + {{::translate.load("kn.qbe.selectgridpanel.buttons.tt.deleteall")}} + + + - - - {{::translate.load("kn.qbe.filtergridpanel.buttons.tt.delete")}} - - - + + + {{::translate.load("kn.qbe.filtergridpanel.buttons.tt.delete")}} + + + - + {{::translate.load("kn.qbe.custom.table.show.hidden.columns.tooltip")}} - - {{::translate.load("kn.qbe.custom.table.smartdata")}} + + {{::translate.load("kn.qbe.custom.table.smartdata")}} - + {{::translate.load('kn.qbe.execute')}} @@ -51,7 +56,7 @@ {{::translate.load('kn.qbe.calculatedFields.parameters')}} - + {{::translate.load('kn.qbe.calculatedFields')}} @@ -65,11 +70,10 @@ -
- +
+
- - + @@ -89,219 +93,170 @@
-
-
{{field.entity}}
- -
- - {{field.name}} - - - -

- {{field.alias}} - {{field.alias}} -

- - - - {{::translate.load("kn.qbe.custom.table.column.settings")}} - - - - - - - {{::translate.load("kn.qbe.custom.table.show.field")}} - - - - - - {{::translate.load("kn.qbe.selectgridpanel.name.temporalOperand.parameter")}} - - - - - - - {{::translate.load("kn.qbe.custom.table.function.temporal")}} - - - - - - - YTD - - - - - - LAST_YEAR - - - - - - PARALLEL_YEAR - - - - - - MTD - - - - - - LAST_MONTH - - - - - - - - - - {{::translate.load("kn.qbe.custom.table.group")}} - - - - - - - - {{::translate.load("kn.qbe.custom.table.aggregation")}} - - - - - - - {{::translate.load("kn.qbe.custom.table.none")}} - - - - - - {{::translate.load("kn.qbe.custom.table.sum")}} - - - - - - {{::translate.load("kn.qbe.custom.table.min")}} - - - - - {{::translate.load("kn.qbe.custom.table.max")}} - - - - - - {{::translate.load("kn.qbe.custom.table.avg")}} - - - - - - {{::translate.load("kn.qbe.custom.table.count")}} - - - - - - {{::translate.load("kn.qbe.custom.table.count.distinct")}} - - - - - - - - - - - - {{::translate.load("kn.qbe.custom.table.move.left")}} - - - - - - {{::translate.load("kn.qbe.custom.table.move.right")}} - - - - - - - {{::translate.load("kn.qbe.general.alias")}} - - - - - - - - {{::translate.load("kn.qbe.custom.table.delete.column")}} - - -
-
- -
{{row.value |format:field:row }} 
- - -
- - - - - - - - -
-
-
-
+ +
+
+ +
-
-
- - {{(start * itemsPerPage) + 1}} to {{maxPageNumber()}} of {{results}} - - -
- -
-
- -
- Page {{start + 1}} of {{totalPages}} -
- -
-
- -
-
-
+
+
+ + {{(start * itemsPerPage) + 1}} to {{maxPageNumber()}} of {{results}} + + +
+ + +
+
+ + +
+ Page {{start + 1}} of {{totalPages}} +
+ +
+
+ +
+
- +
+
\ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/customTable.js b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/customTable.js index 4789f23acb5..9f1fee96b35 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/customTable.js +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/custom-table/customTable.js @@ -72,11 +72,220 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM //$scope.smartPreview = query_service.smartView; $scope.query_service = query_service; $scope.completeResult = false; + $scope.hideList = $scope.$parent.hideList; + $scope.toggleEntitiesList = function(){ + $scope.hideList = !$scope.hideList; + $scope.$parent.hideList = !$scope.$parent.hideList; + } $scope.completeResultsColumns = []; $scope.previewModel = []; + function CustomPinnedRowRenderer() {} + CustomPinnedRowRenderer.prototype.init = function(params) { + var fieldName = params.colDef.field; + this.data = params.data[fieldName]; + + this.eGui = document.createElement('div'); + this.eGui.classList.add("customFooter"); + + var filterClass = ''; + if(params.value && params.value.filters && params.value.filters.length > 0){ + filterClass = 'filter-color'; + } + this.eGui.innerHTML = ''+ + ''; + + var onInfoButtonClick = this.infoColumn.bind(this); + var onFilterButtonClick = this.filterColumn.bind(this); + + var infoIconEl = this.eGui.querySelector(".info-button"); + infoIconEl.addEventListener("click", onInfoButtonClick); + + var filterIconEl = this.eGui.querySelector(".filter-button"); + filterIconEl.addEventListener("click", onFilterButtonClick); + }; + CustomPinnedRowRenderer.prototype.getGui = function() { + return this.eGui; + }; + CustomPinnedRowRenderer.prototype.infoColumn = function() { + $scope.showFilters(this.data); + }; + CustomPinnedRowRenderer.prototype.filterColumn = function() { + $scope.openFilters(this.data); + }; + + $scope.qbeTableGrid = { + angularCompileRows: true, + pagination : false, + domLayout:'autoHeight', + rowHeight: 20, + defaultColDef: { + resizable: true, + pinnedRowCellRenderer: CustomPinnedRowRenderer + }, + components: { + agColumnHeader: CustomHeader + } + } + + //VALUE FORMATTERS + function dateTimeFormatter(params){ + return isNaN(moment(params.value,'DD/MM/YYYY HH:mm:ss.SSS'))? params.value : moment(params.value,'DD/MM/YYYY HH:mm:ss.SSS').locale(sbiModule_config.curr_language).format(params.colDef.properties.format || 'LLL'); + } + + function numberFormatter(params){ + switch(params.colDef.properties.format) { + case '#,###': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 0 }).format(params.value) + case '#,###.0': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 1 }).format(params.value) + case '#,###.00': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 2 }).format(params.value) + case '#,###.000': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 3 }).format(params.value) + case '#,###.0000': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 4 }).format(params.value) + case '#,###.00000': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 5 }).format(params.value) + case '€#.##0.00': + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 2 , style: 'currency', currency: 'EUR' }).format(params.value) + case "€#,##0.00": + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 2 , style: 'currency', currency: 'EUR' }).format(params.value) + case '$#,##0.00': + return new Intl.NumberFormat('en-US', { minimumFractionDigits: 2 , style: 'currency', currency: 'USD' }).format(params.value) + default: + return new Intl.NumberFormat(sbiModule_config.curr_language + '-' + sbiModule_config.curr_country, { minimumFractionDigits: 0 }).format(params.value) + } + } + + + //CUSTOM RENDERERS + function CustomHeader() {} + CustomHeader.prototype.init = function(params) { + + this.params = params; + this.properties = params.column.colDef.properties; + + this.eGui = document.createElement("div"); + this.eGui.classList.add("customHeader"); + this.eGui.innerHTML = '
' + + '
' + + '' + params.displayName + '' + + ''+ + '
'; + + this.onRemoveButtonClick = this.removeColumn.bind(this); + this.onSortButtonClick = this.sortColumn.bind(this); + this.onSettingsButtonClick = this.openColumnSettings.bind(this); + + this.removeButton = this.eGui.querySelector(".remove-button"); + this.removeButton.addEventListener("click", this.onRemoveButtonClick); + + this.sortButton = this.eGui.querySelector(".sort-button"); + this.sortButton.addEventListener("click", this.onSortButtonClick); + + this.settingsButton = this.eGui.querySelector(".settings-button"); + this.settingsButton.addEventListener("click", this.onSettingsButtonClick); + + + } + CustomHeader.prototype.getGui = function() { + return this.eGui; + } + CustomHeader.prototype.removeColumn = function() { + $scope.removeColumns([{"id" : this.properties.id,"entity" : this.properties.entity }]); + } + CustomHeader.prototype.sortColumn = function() { + var realColumn = $scope.getColumnById(this.properties.id) + $scope.toggleOrder(realColumn); + $scope.executeRequest(); + } + CustomHeader.prototype.openColumnSettings = function(event){ + for(var k in $scope.ngModel){ + if($scope.ngModel[k].id == this.properties.id) $scope.field = $scope.ngModel[k]; + } + document.getElementById('ag-popup-child').style.left = event.clientX; + document.getElementById('ag-popup-child').style.top = event.clientY; + $scope.$apply(); + togglePopupVisibility(); + } + + function togglePopupVisibility(){ + var agPopUpEl = document.getElementById('ag-popup'); + var agPopUpCloseAreaEl = document.getElementById('ag-popup-close-area'); + + agPopUpEl.style.display = agPopUpEl.style.display == 'block' ? 'none' : 'block'; + agPopUpCloseAreaEl.style.display = agPopUpEl.style.display; + } + + function isTemporal(type){ + if(['oracle.sql.TIMESTAMP','java.sql.Timestamp','java.util.Date','java.sql.Date','java.sql.Time'].indexOf(type) > -1) return true; + else return false; + } + + function isNumeric(type){ + if(["java.lang.Byte","java.lang.Long","java.lang.Short","java.lang.Integer","java.math.BigInteger","java.lang.Double","java.lang.Float","java.math.BigDecimal","java.math.Decimal" ].indexOf(type) > -1) return true; + else return false; + } + + function getAgGridColumns() { + return $scope.ngModel + .map(function(el) { + var tempObj = {"field": el.key, + "tooltipField": el.key, + "headerName": el.alias, + "hide": !el.visible, + "properties": { + "entity": el.entity, + "id": el.id, + "color": el.color + } + } + if(isTemporal(el.dataType)) { + tempObj.valueFormatter = dateTimeFormatter; + tempObj.properties.format = el.format; + } + if(isNumeric(el.dataType)) { + tempObj.valueFormatter = numberFormatter; + tempObj.properties.format = el.format; + } + return tempObj; + }); + } + + $scope.closePopup = function() { + togglePopupVisibility(); + } + + $scope.getColumnById = function(id) { + return $scope.ngModel + .find(function(el) { + return el.id == id; + }) + } + + $scope.updateQbeTableGridColDef = function() { + $scope.qbeTableGrid.api.setColumnDefs(getAgGridColumns()); + } + + $scope.updateQbeTableGridData = function() { + $scope.qbeTableGrid.api.setRowData($scope.previewModel); + + var pinnedBottomRowData = $scope.ngModel.reduce(function(accumulator, currentValue, index) { + accumulator["column_" + (index + 1)] = currentValue; + return accumulator; + }, {}); + + $scope.qbeTableGrid.api.setPinnedBottomRowData([pinnedBottomRowData]); + } + + $scope.updateQbeTable = function() { + $scope.updateQbeTableGridColDef(); + $scope.updateQbeTableGridData(); + } + // PAGINATION METHODS $scope.pageChanged = function(newPageNumber){ $rootScope.$broadcast('start',{"itemsPerPage":$scope.itemsPerPage, "currentPageNumber":newPageNumber}); @@ -145,6 +354,10 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM expression_service.generateExpressions($scope.filters,$scope.expression,$scope.advancedFilters) } + + $scope.deleteColumn = function(column){ + $scope.ngModel.splice($scope.ngModel.indexOf(column),1); + } $scope.moveRight = function(currentOrder, column) { @@ -231,12 +444,13 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM $rootScope.$broadcast('showCalculatedField',row); } - $scope.removeColumns = function(fields) { + $scope.removeColumns = function(fields,standardTable) { var toRemove = []; for(var i in fields){ toRemove.push({"id" : fields[i].id,"entity" : fields[i].entity }) } + if(!standardTable) $scope.updateQbeTable(); $rootScope.$emit('removeColumns', toRemove); }; @@ -277,6 +491,7 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM $scope.openPreviewTemplate(true, $scope.completeResultsColumns, $scope.previewModel, data.results); $scope.firstExecution = false; } + $scope.updateQbeTable(); }); $scope.$on('start', function (event, data) { @@ -300,7 +515,6 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM fullscreen :true, controller: function($scope,mdPanelRef,sbiModule_translate,$mdDateLocale){ - var gridOptions = { enableColResize: true, enableSorting: false, @@ -340,12 +554,46 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM gridOptions.api.sizeColumnsToFit(); } $scope.model ={"gridOptions":gridOptions, "completeresult": completeResult, "completeResultsColumns": completeResultsColumns, "previewModel": previewModel, "totalNumberOfItems": totalNumberOfItems, "mdPanelRef":mdPanelRef}; - $scope.$watch('model.previewModel',function(){ - console.log($scope.model) - gridOptions.api.setRowData($scope.model.previewModel); + $scope.$watch('model.previewModel',function(newValue,oldValue){ + console.log(newValue) + gridOptions.api.setRowData(newValue); + $scope.totalPages = Math.ceil($scope.model.totalNumberOfItems / $scope.itemsPerPage); },true) $scope.itemsPerPage = 20; + $scope.currentPageNumber = 0; + $scope.maxPageNumber = function(){ + if(($scope.currentPageNumber + 1) * $scope.itemsPerPage < $scope.model.totalNumberOfItems) return ($scope.currentPageNumber + 1) * $scope.itemsPerPage; + else return $scope.model.totalNumberOfItems; + } + + $scope.disableFirst = function(){ + return $scope.currentPageNumber == 0; + } + + $scope.disableLast = function(){ + return ($scope.currentPageNumber + 1) == $scope.totalPages; + } + + $scope.first = function(){ + $scope.currentPageNumber = 0; + $scope.changeDatasetPage($scope.itemsPerPage,1); + } + + $scope.prev = function(){ + $scope.currentPageNumber--; + $scope.changeDatasetPage($scope.itemsPerPage,$scope.currentPageNumber); + } + + $scope.next = function(){ + $scope.currentPageNumber++; + $scope.changeDatasetPage($scope.itemsPerPage,$scope.currentPageNumber + 2); + } + + $scope.last = function(){ + $scope.currentPageNumber = $scope.totalPages -1; + $scope.changeDatasetPage($scope.itemsPerPage,$scope.totalPages -1); + } $scope.changeDatasetPage=function(itemsPerPage,currentPageNumber){ $rootScope.$broadcast('start',{"itemsPerPage":itemsPerPage, "currentPageNumber":currentPageNumber}); @@ -594,7 +842,7 @@ function qbeCustomTable($scope, $rootScope, $mdDialog, sbiModule_translate, sbiM orderingValues: ["NONE", "ASC", "DESC"], temporalFunctions: $scope.tmpFunctions, deleteField : function (row) { - $scope.removeColumns([row]); + $scope.removeColumns([row],true); }, moveUp : function (row) { $scope.moveLeft(row.order, row); diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/filter/filter.js b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/filter/filter.js index 1dc8397bb2f..be31e0a23fc 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/directive/filter/filter.js +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/directive/filter/filter.js @@ -464,7 +464,6 @@ function qbeFilter($scope,$rootScope, sbiModule_user,filters_service , sbiModule $scope.paramsPreviewGrid = { rowData: $scope.pars, angularCompileRows: true, - stopEditingWhenGridLosesFocus:true, enableColResize: false, enableFilter: true, enableSorting: true, diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages.properties b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages.properties index 6d922026156..857ec4b26b2 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages.properties +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages.properties @@ -61,7 +61,7 @@ kn.crosstab.crosstabdetailswizard.percenton kn.crosstab.crosstabdetailswizard.row = rows kn.crosstab.crosstabdetailswizard.rows = rows kn.crosstab.crosstabdetailswizard.title = Crosstab details -kn.crosstab.crosstabpreviewpanel.overflow.warning = The cells number is highter than the default one. You can find all the data with the XLS export. +kn.crosstab.crosstabpreviewpanel.overflow.warning = The cells number is higher than the default one. You can find all the data with the XLS export. kn.crosstab.crosstabpreviewpanel.title = Crosstab preview kn.crosstab.crossTabValidation.noAttribute = You have not included any attribute in pivot table kn.crosstab.crossTabValidation.noMandatoryMeasure = Mandatory Measure must be included @@ -88,7 +88,7 @@ kn.dataset.parametersgridpanel.columns.name kn.dataset.parametersgridpanel.columns.type = Type kn.dataset.parametersgridpanel.title = Parameters kn.designerchart.chartValidation.noCategory = Use one attribute as category -kn.designerchart.chartValidation.noSeries = Use at least one measure as serie +kn.designerchart.chartValidation.noSeries = Use at least one measure as series kn.designertable.tableValidation.noElement = At least one attribute or measure must be inserted kn.ds.catType = Category kn.ds.field.metadata = Field metadata @@ -167,7 +167,7 @@ kn.formbuilder.inlineeditor.remove kn.formbuilder.queryfieldspanel.fieldname = Field name kn.formbuilder.queryfieldspanel.title = Selected fields kn.formbuilder.queryfieldspanel.tools.refresh = Refresh query fields -kn.formbuilder.staticclosefiltereditorpanel.emptymsg = Click on the button in the top-rigtht corner in order to add a new filter group +kn.formbuilder.staticclosefiltereditorpanel.emptymsg = Click on the button in the top-right corner in order to add a new filter group kn.formbuilder.staticclosefiltereditorpanel.filteritemname = static closed filters group kn.formbuilder.staticclosefiltereditorpanel.title = Static closed filters kn.formbuilder.staticclosefiltergroupeditor.toolbar.add = Add @@ -253,7 +253,7 @@ kn.generic.error kn.generic.helpOnLine= Help OnLine kn.generic.label = Label kn.generic.name = Name -kn.generic.operationSucceded = Operation succeded +kn.generic.operationSucceded = Operation succeeded kn.generic.query.JPQL = JPLQ Query kn.generic.query.SQL = SQL Query kn.generic.scope = Scope @@ -348,8 +348,10 @@ kn.qbe.custom.table.delete.column = Delete column kn.qbe.custom.table.delete.field = Delete field kn.qbe.custom.table.distinct = Discard Repetitions kn.qbe.custom.table.entity = Entity +kn.qbe.custom.table.filters = Column Filters kn.qbe.custom.table.function.temporal = Temporal Function kn.qbe.custom.table.group = Group +kn.qbe.custom.table.info = Info kn.qbe.custom.table.max = Max kn.qbe.custom.table.min = Min kn.qbe.custom.table.move.down = Move down @@ -363,6 +365,7 @@ kn.qbe.custom.table.ranges = Ranges kn.qbe.custom.table.show.field = Show field kn.qbe.custom.table.show.hidden.columns.tooltip = Show hidden columns kn.qbe.custom.table.smartdata = Smart view +kn.qbe.custom.table.sorting = Sorting kn.qbe.custom.table.sum = Sum kn.qbe.custom.table.toolbar.main = Main kn.qbe.custom.table.toolbar.join.definition = Join Definitions @@ -443,7 +446,7 @@ kn.qbe.filtergridpanel.foperators.desc.gt kn.qbe.filtergridpanel.foperators.desc.in = true if the field's value is equal to one of the values specified in the filter value kn.qbe.filtergridpanel.foperators.desc.isnull = true if the field's value is null kn.qbe.filtergridpanel.foperators.desc.lt = true if the field's value is less than filter's value -kn.qbe.filtergridpanel.foperators.desc.none = no filter applyed +kn.qbe.filtergridpanel.foperators.desc.none = no filter applied kn.qbe.filtergridpanel.foperators.desc.notbetween = true if the field's value is not between the range specified in the filter value kn.qbe.filtergridpanel.foperators.desc.notcontains = true if the field's value doesn't contain filter's value kn.qbe.filtergridpanel.foperators.desc.notends = true if the field's value doesn't end with filter's value @@ -538,11 +541,11 @@ kn.qbe.filtergridpanel.tooltip.rodesc kn.qbe.filtergridpanel.tooltip.rolast = Right operand last value kn.qbe.filtergridpanel.tooltip.rotype = Right operand type kn.qbe.filtergridpanel.tooltip.roval = Right operand value -kn.qbe.filtergridpanel.warning.changebolop.msg = Changing the boolean connector of this filter will reset the associated neasted expression (see expression wizard). Would you like to go on anyway? +kn.qbe.filtergridpanel.warning.changebolop.msg = Changing the boolean connector of this filter will reset the associated nested expression (see expression wizard). Would you like to go on anyway? kn.qbe.filtergridpanel.warning.changebolop.title = Change boolean connector? -kn.qbe.filtergridpanel.warning.delete.msg = Your are removing a filter that is used in a neasted expression (see expression wizard). Removing it will reset the expression. Would you like to go on anyway? +kn.qbe.filtergridpanel.warning.delete.msg = Your are removing a filter that is used in a nested expression (see expression wizard). Removing it will reset the expression. Would you like to go on anyway? kn.qbe.filtergridpanel.warning.delete.title = Remove filter? -kn.qbe.filtergridpanel.warning.deleteAll.msg = You are going to delete all filtres. Do you want to go on? +kn.qbe.filtergridpanel.warning.deleteAll.msg = You are going to delete all filters. Do you want to go on? kn.qbe.filtergridpanel.warning.deleteAll.title = Delete all filters? kn.qbe.filters = Filter kn.qbe.filters.add.new.filter = Add new filter @@ -552,7 +555,7 @@ kn.qbe.filters.condition = Condition kn.qbe.filters.field = Field kn.qbe.filters.nofilters = No filter present, add one with the plus button on the right corner. kn.qbe.filters.operators.between = Between -kn.qbe.filters.operators.contains = Containes +kn.qbe.filters.operators.contains = Contains kn.qbe.filters.operators.ends.with = Ends with kn.qbe.filters.operators.equals.or.greater.than = Equals or greater than kn.qbe.filters.operators.equals.or.less.than = Equals or less than @@ -562,7 +565,7 @@ kn.qbe.filters.operators.in = In kn.qbe.filters.operators.is.null = Is null kn.qbe.filters.operators.less.than = Less than kn.qbe.filters.operators.not.between = Not between -kn.qbe.filters.operators.not.contains = Not containes +kn.qbe.filters.operators.not.contains = Not contains kn.qbe.filters.operators.not.ends.with = Not ends with kn.qbe.filters.operators.not.equals.to = Not equals to kn.qbe.filters.operators.not.in = Not in @@ -651,7 +654,7 @@ kn.qbe.params.multivalue = Multivalue kn.qbe.params.name = Name kn.qbe.params.no.dataset.params = Dataset has no parameters to delete kn.qbe.params.noparameters = No parameter present, add one with the plus button on the right corner. -kn.qbe.params.duplicated = Duplicated parameter names !!! +kn.qbe.params.duplicated = Duplicated parameter names!!! kn.qbe.params.number = Number kn.qbe.params.raw = Raw kn.qbe.params.string = String @@ -680,15 +683,15 @@ kn.qbe.queryeditor.eastregion.tools.insert kn.qbe.queryeditor.eastregion.tools.wanringEraseRoot = Cannot erase root query kn.qbe.queryeditor.error.FILTER_ROLES_ERROR = If you are using entities with more than one role, in that entities you can specify filters only in the selected fields kn.qbe.queryeditor.msgwarning = The query is incorrect; do you want to save it anyway? -kn.qbe.queryeditor.noambiguousfields.msg = There are no ambiguous fieds in the current query -kn.qbe.queryeditor.noambiguousfields.title = No ambiguous fieds +kn.qbe.queryeditor.noambiguousfields.msg = There are no ambiguous fields in the current query +kn.qbe.queryeditor.noambiguousfields.title = No ambiguous fields kn.qbe.queryeditor.querysaved = Query saved kn.qbe.queryeditor.querysavedsucc = Query saved successfully kn.qbe.queryeditor.saveqasview = Save query as view... kn.qbe.queryeditor.savequery = Save query ... kn.qbe.queryeditor.title = Query kn.qbe.queryeditor.westregion.title = Schema -kn.qbe.queryeditor.westregion.tools.addcalculated = Add calulated field +kn.qbe.queryeditor.westregion.tools.addcalculated = Add calculated field kn.qbe.queryeditor.westregion.tools.collapse = Collapse all kn.qbe.queryeditor.westregion.tools.expand = Expand all kn.qbe.queryeditor.westregion.tools.flat = Flat view @@ -754,7 +757,7 @@ kn.qbe.selectgridpanel.aggfunc.desc.min kn.qbe.selectgridpanel.aggfunc.desc.none = No aggregation function applied kn.qbe.selectgridpanel.aggfunc.desc.sum = Return the sum of all values in group kn.qbe.selectgridpanel.aggfunc.editor.emptymsg = Select a function... -kn.qbe.selectgridpanel.aggfunc.name.avg = averege +kn.qbe.selectgridpanel.aggfunc.name.avg = average kn.qbe.selectgridpanel.aggfunc.name.count = count kn.qbe.selectgridpanel.aggfunc.name.countdistinct = count distinct kn.qbe.selectgridpanel.aggfunc.name.max = maximum @@ -769,7 +772,7 @@ kn.qbe.selectgridpanel.buttons.text.expert kn.qbe.selectgridpanel.buttons.text.group = Group by entity kn.qbe.selectgridpanel.buttons.text.hide = Hide non-visible kn.qbe.selectgridpanel.buttons.tt.add = Add an ad-hoc calculated field (i.e. valid only for this query) -kn.qbe.selectgridpanel.buttons.tt.delete = Delete selected filed +kn.qbe.selectgridpanel.buttons.tt.delete = Delete selected field kn.qbe.selectgridpanel.buttons.tt.deleteall = Delete all selected fields kn.qbe.selectgridpanel.buttons.tt.group = Group fields by parent entity kn.qbe.selectgridpanel.buttons.tt.hide = Hide all non visible fields @@ -826,9 +829,9 @@ kn.qbe.selectgridpanel.name.temporalOperand.parameter = Temporal parame kn.qbe.selectgridpanel.name.temporalOperand.qtd = QTD kn.qbe.selectgridpanel.name.temporalOperand.wtd = WTD kn.qbe.selectgridpanel.name.temporalOperand.ytd = YTD -kn.qbe.selectgridpanel.sortfunc.desc.asc = Order values of the given column in asecnding way +kn.qbe.selectgridpanel.sortfunc.desc.asc = Order values of the given column in ascending way kn.qbe.selectgridpanel.sortfunc.desc.desc = Order values of the given column in descending way -kn.qbe.selectgridpanel.sortfunc.desc.none = No ordering applied to the given colunm +kn.qbe.selectgridpanel.sortfunc.desc.none = No ordering applied to the given column kn.qbe.selectgridpanel.sortfunc.editor.emptymsg = Select ordering direction... kn.qbe.selectgridpanel.sortfunc.name.asc = ascending kn.qbe.selectgridpanel.sortfunc.name.desc = descending @@ -866,7 +869,7 @@ kn.qbe.selectgridpanel.spatial.desc.length kn.qbe.selectgridpanel.spatial.desc.longitude = Retrieve longitude of given point kn.qbe.selectgridpanel.spatial.desc.relate = Examines two geometry objects to determine their spatial relationship kn.qbe.selectgridpanel.spatial.desc.toKM = Converts the given Nautical Mile value to Kilometer -kn.qbe.selectgridpanel.spatial.desc.toNM = Converts the given Kilometer value to Nautic Mile +kn.qbe.selectgridpanel.spatial.desc.toNM = Converts the given Kilometer value to Nautical Mile kn.qbe.selectgridpanel.spatial.desc.union = Returns a geometric object that is the topological union (OR operation) of two geometry objects kn.qbe.selectgridpanel.title = Select Fields kn.qbe.sessionexpired.msg = Session has expired. @@ -874,11 +877,11 @@ kn.qbe.temporalfilter.title = Temporal filter kn.registry.document.delete.confirm.message = Are you sure you want to delete row? kn.registry.document.delete.row = Delete Row kn.registry.registryDocument.column = Column/s -kn.registry.registryDocument.delete.success = You have succesufly deleted row! +kn.registry.registryDocument.delete.success = You have successfully deleted row! kn.registry.registryDocument.dontWarn = Don't Warn Me Again kn.registry.registryDocument.row = row/s kn.registry.registryDocument.success = Success!!! -kn.registry.registryDocument.update.success = You have succesufly updated +kn.registry.registryDocument.update.success = You have successfully updated kn.registry.registryDocument.warning.title = Warning kn.registry.registryDocument.warningDependences = depend/s from this value. Please check them and set correct values! kn.registry.registryeditorgridpanel.mandatory = : mandatory field @@ -888,7 +891,7 @@ kn.registry.registryeditorgridpanel.saveconfirm.title kn.registry.registryeditorgridpanel.validation = Validation error: numeric field kn.registry.registryeditorgridpanel.validation.unsigned = Validation error: signed values not allowed kn.registry.registryeditorgridpanel.warningDependences.1 = Some fields like -kn.registry.registryeditorgridpanel.warningDependences.2 = depend from this value. Please check them and set correct values ! +kn.registry.registryeditorgridpanel.warningDependences.2 = depend from this value. Please check them and set correct values! kn.registry.registrypanel.title = Registry sbi.general.ok = Ok sbi.general.cancel = Cancel diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_it_IT.properties b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_it_IT.properties index 163462e12fa..7ccc3b73853 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_it_IT.properties +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_it_IT.properties @@ -280,6 +280,7 @@ kn.qbe.calculatedfield.type=Tipo kn.qbe.calculatedfield.dateFormat=Formato Data kn.qbe.calculatedfield.validate=validare kn.qbe.calculatedfield.nature=Natura +kn.qbe.calculatedFields=Campi calcolati kn.qbe.calculatedFields.add=Aggiungere campo calcolato kn.qbe.calculatedFields.add.error=Impossibile aggiungere campo calcolato ad un nodo di tipo [{0}] kn.qbe.calculatedFields.aggrfunctions=Funzioni di aggregazione @@ -371,6 +372,7 @@ kn.qbe.documentparametersgridpanel.emptytext=Questo doocuemnto non ha driver ana kn.qbe.documentparametersgridpanel.headers.label=Titolo kn.qbe.documentparametersgridpanel.parameterreference=Driver analitico kn.qbe.documentparametersgridpanel.title=Driver analitici del documento +kn.qbe.execute=Esegui anteprima kn.qbe.expander.list.add.temporal.filter=È possibile aggiungere filtri temporali in questo campo kn.qbe.expander.list.derived.entities=Entità derivate kn.qbe.expander.list.entities=Entità @@ -391,6 +393,7 @@ kn.qbe.expreditor.operators=Operatori kn.qbe.expreditor.refresh=Aggiornare la struttura dell'espressione kn.qbe.expreditor.structure=Esp. Struttura kn.qbe.expreditor.title=Editor dell'espressione +kn.qbe.filter.advanced=Filtro avanzato kn.qbe.filtergridpanel.boperators.desc.and=Connetti questo filtro e il prossimo usando l'operatore booleano AND kn.qbe.filtergridpanel.boperators.desc.or=Connetti questo filtro e il prossimo usando l'operatore booleano OR kn.qbe.filtergridpanel.boperators.editor.emptymsg=Selezionare un operatore @@ -621,7 +624,7 @@ kn.qbe.params.multivalue=Multivalore kn.qbe.params.name=Nome kn.qbe.params.no.dataset.params=Il dataset non ha parametri da eliminare kn.qbe.params.noparameters=Non sono presenti parametri, aggiungerne uno con il bottone "più" nell'angolo destro. -kn.qbe.params.duplicated=Nome del parametro duplicato\!\! +kn.qbe.params.duplicated=Nome del parametro duplicato kn.qbe.params.number=Numero kn.qbe.params.raw=Grezzo kn.qbe.params.string=Stringa @@ -844,11 +847,11 @@ kn.qbe.temporalfilter.title=Filtro temporale kn.registry.document.delete.confirm.message=Coonfermare l'eliminazione della riga? kn.registry.document.delete.row=Eliminare riga kn.registry.registryDocument.column=Colonna/e -kn.registry.registryDocument.delete.success=Riga eliminata con successo\! +kn.registry.registryDocument.delete.success=Riga eliminata con successo kn.registry.registryDocument.dontWarn=Non avvertirmi nuovamente kn.registry.registryDocument.row=riga/righe kn.registry.registryDocument.success=Successo\! -kn.registry.registryDocument.update.success=Hai aggiornato con successo +kn.registry.registryDocument.update.success=Aggiornamento avvenuto con successo kn.registry.registryDocument.warning.title=Attenzione kn.registry.registryDocument.warningDependences=dipende/dipendono da questo valore. Verifica(li) e imposta i valori corretti\! kn.registry.registryeditorgridpanel.mandatory=\: campo obbligatorio diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_zh_Hans_CN.properties b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_zh_Hans_CN.properties index 3b95f2c56ae..c87e8e1dcee 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_zh_Hans_CN.properties +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/messages/messages_zh_Hans_CN.properties @@ -125,7 +125,6 @@ kn.formbuilder.staticclosefiltergroupwizard.fields.enablesingleselection.label= kn.formbuilder.staticclosefiltergroupwizard.fields.enablesingleselection.no=否 kn.formbuilder.staticclosefiltergroupwizard.fields.enablesingleselection.yes=是 kn.formbuilder.staticclosefiltergroupwizard.fields.grouptitle.label=名称 -kn.formbuilder.staticclosefiltergroupwizard.fields.noselectionoptionlabel.label=没有选择选项的标签 kn.formbuilder.staticclosefiltergroupwizard.fields.noselectiontext=所有 kn.formbuilder.staticclosefiltergroupwizard.fields.options=选项 kn.formbuilder.staticclosefilterwizard.buttons.apply=应用 @@ -178,7 +177,6 @@ kn.generic.error=错误 kn.generic.helpOnLine=在线帮助 kn.generic.label=标签 kn.generic.name=名称 -kn.generic.operationSucceded=操作成功 kn.generic.query.JPQL=JPLQ查询 kn.generic.query.SQL=SQL查询 kn.generic.scope=范围 @@ -412,7 +410,6 @@ kn.qbe.savewindow.saveas=另存为... kn.qbe.savewindow.scope=范围 kn.qbe.savewindow.selectmetadata=插入元数据 kn.qbe.savewindow.selectscope=选择范围... -kn.qbe.selectgridpanel.aggfunc.name.avg=平均 kn.qbe.selectgridpanel.aggfunc.name.count=计数 kn.qbe.selectgridpanel.aggfunc.name.countdistinct=不同计数 kn.qbe.selectgridpanel.aggfunc.name.max=最大 @@ -425,7 +422,6 @@ kn.qbe.selectgridpanel.buttons.text.deleteall=删除所有 kn.qbe.selectgridpanel.buttons.text.expert=专家用户 kn.qbe.selectgridpanel.buttons.text.group=依据实体分组 kn.qbe.selectgridpanel.buttons.text.hide=隐藏不可见 -kn.qbe.selectgridpanel.buttons.tt.delete=删除选择字段 kn.qbe.selectgridpanel.buttons.tt.deleteall=删除所有选择字段 kn.qbe.selectgridpanel.buttons.tt.hide=隐藏所有不可见字段 kn.qbe.selectgridpanel.func.pipe.tip=管道 @@ -448,7 +444,6 @@ kn.registry.document.delete.row=删除行 kn.registry.registryDocument.column=列 kn.registry.registryDocument.row=行 kn.registry.registryDocument.success=成功\!\!\! -kn.registry.registryDocument.update.success=您已经成功更新 kn.registry.registryDocument.warning.title=警告 kn.registry.registryeditorgridpanel.saveconfirm.message.ko=操作失败 kn.registry.registryeditorgridpanel.saveconfirm.title=状态 diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/services/queries/queries.js b/knowageqbeengine/src/main/webapp/js/src/qbe/services/queries/queries.js index 5b2c7663070..1823505b21f 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/services/queries/queries.js +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/services/queries/queries.js @@ -31,14 +31,13 @@ queries.service('query_service',function(sbiModule_restServices,sbiModule_config for (var i = 0; i < query.fields.length; i++) { - var queryObject = { "id":query.fields[i].id, + "key": "column_" + (i+1), "name":query.fields[i].field, "alias":query.fields[i].alias, "entity":query.fields[i].entity, "color":query.fields[i].color, - "data":getRows(query.fields[i].alias,response.data), "funct":query.fields[i].funct, "fieldType" : query.fields[i].fieldType, "dataType": query.fields[i].dataType, diff --git a/knowageqbeengine/src/main/webapp/js/src/qbe/templates/datasetPreviewDialogTemplate.html b/knowageqbeengine/src/main/webapp/js/src/qbe/templates/datasetPreviewDialogTemplate.html index b2a0059c4ce..ddae66853e8 100644 --- a/knowageqbeengine/src/main/webapp/js/src/qbe/templates/datasetPreviewDialogTemplate.html +++ b/knowageqbeengine/src/main/webapp/js/src/qbe/templates/datasetPreviewDialogTemplate.html @@ -1,34 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -42,18 +11,42 @@
+
+
+
+ + {{(currentPageNumber * itemsPerPage) + 1}} to {{maxPageNumber()}} of {{model.totalNumberOfItems}} + + +
+ +
+
+ +
+ Page {{currentPageNumber + 1}} of {{totalPages}} +
+ +
+
+ +
+
+
+
+
- +
diff --git a/knowageqbeengine/src/main/webapp/js/src/registry/css/registry.css b/knowageqbeengine/src/main/webapp/js/src/registry/css/registry.css deleted file mode 100644 index a4f180d5913..00000000000 --- a/knowageqbeengine/src/main/webapp/js/src/registry/css/registry.css +++ /dev/null @@ -1,122 +0,0 @@ -.kn-registry .clickable { - cursor: pointer; - min-width: 100px; - min-height: 20px; -} - -.md-scroll-mask { - z-index: 1 !important; -} - -.kn-registry .md-open-menu-container { - z-index: 80; -} - -.kn-registry md-backdrop { - z-index: 10; -} - -.kn-registry .registryFilters { - background: white; - box-shadow: 0px 2px 5px #ccc; - z-index: 9; - position: relative; - margin: 5px; - border: 4px solid #A9C3DB; -} - -.kn-registry .registryFilters .registryFilter { - min-width: 200px; - margin-bottom: 4px; -} - -.kn-table { - width: auto; -} - -.kn-table.alternatedRows tbody tr:nth-child(odd) { - background-color: #f0f0f0; -} - -.kn-table tbody tr md-icon { - line-height: 20px; - height: 20px; - min-height: 20px; - max-height: 20px; -} - -.recNo { - width: 50px; - border-right: 2px solid #e6e6e6; -} - -.kn-table thead th.tableAction { - width: 50px; -} - -.kn-table .innerTable { - width: 100%; -} - -.kn-table .innerTable tr { - background-color: transparent !important; -} - -.customContentMenu .check { - width: 46px; -} - -.blue { - background-color: #dbe6f0 !important; -} - -.pivot-table th, .pivot-table tr, .pivot-table td { - border: 3px solid #A9C3DB; -} - -.pivot-table thead { - border: 3px solid #81a7ca; -} - -.pagination { - margin-top: 20px; -} -.label { - color: black; -} - -md-select { - margin: 0; -} - -.filter-btns, .delete-row { - cursor: pointer; -} - -.filter-clear, .filter { - margin: 0 10px; -} - -.save-btn { - position: absolute; - right: 20px; -} -.sortorder:hover:after { - content: '\25b2'; /* BLACK UP-POINTING TRIANGLE */ -} -.sortorder.reverse:hover:after { - content: '\25bc'; /* BLACK DOWN-POINTING TRIANGLE */ -} - -.customDialog { - padding: 20px; - max-width: 600px; -} - -.customDialog .button { - padding: 8px 28px; - background-color: #A9C3DB; - font-weight: bold; - border: none; - float: right; -} \ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/js/src/registry/dependentColumnsDialog.tpl.html b/knowageqbeengine/src/main/webapp/js/src/registry/dependentColumnsDialog.tpl.html index cb10a360bc0..db0669d1400 100644 --- a/knowageqbeengine/src/main/webapp/js/src/registry/dependentColumnsDialog.tpl.html +++ b/knowageqbeengine/src/main/webapp/js/src/registry/dependentColumnsDialog.tpl.html @@ -6,7 +6,7 @@

{{translate.load("kn.registry.registryDocument.warning.title")}}

{{translate.load("kn.registry.registryDocument.column")}} - {{dependentColumns.join(', ')}} + {{dependentColumns}} {{translate.load("kn.registry.registryDocument.warningDependences")}}

diff --git a/knowageqbeengine/src/main/webapp/js/src/registry/registry.controller.js b/knowageqbeengine/src/main/webapp/js/src/registry/registry.controller.js index e038234d388..34693213a3a 100644 --- a/knowageqbeengine/src/main/webapp/js/src/registry/registry.controller.js +++ b/knowageqbeengine/src/main/webapp/js/src/registry/registry.controller.js @@ -29,7 +29,13 @@ $httpProvider.interceptors .push('httpInterceptor'); - } ]).controller('RegistryController', ['$scope','registryConfigService', 'registryCRUDService', + } ]) + .filter('momentDate', function() { + return function(input, currLanguage) { + return input ? moment(input).locale(currLanguage).format("L") : ''; + }; + }) + .controller('RegistryController', ['$scope','registryConfigService', 'registryCRUDService', 'regFilterGetData', 'sbiModule_messaging','sbiModule_translate', 'sbiModule_config', '$mdDialog', '$filter', 'orderByFilter','registryPaginationService', RegistryController]) @@ -90,18 +96,20 @@ } else { $scope.formParams.start = 0; } + $scope.currLanguage = sbiModule_config.curr_language; readData($scope.formParams); }; var readData = function(formParameters) { $scope.formatNumber= 0; registryCRUD.read(formParameters).then(function(response) { - $scope.data = response.data.rows; + + $scope.data= $scope.transformDataStore(response.data).rows if($scope.configuration.pagination != 'true'){ $scope.data = orderBy($scope.data,$scope.propertyName,$scope.reverse); } dateColumns = dateColumnsFilter(response.data.metaData.fields); - $scope.data = dateRowsFilter(dateColumns,response.data.rows); + $scope.data = dateRowsFilter(dateColumns,$scope.data); $scope.resultsNumber = response.data.results; $scope.initalizePagination(); if($scope.columnSizeInfo.length == 0) { @@ -114,7 +122,23 @@ }); }; - + $scope.transformDataStore = function (datastore){ + var newDataStore = {}; + newDataStore.metaData = datastore.metaData; + newDataStore.results = datastore.results; + newDataStore.rows = []; + + for(var i=0; i 0) + $scope.joinedFields += ", "; + + $scope.joinedFields += $scope.dependentColumns[k].title + i++; + } + $scope.confirm = $mdDialog.prompt( { controller: DialogController, @@ -405,7 +444,7 @@ templateUrl: sbiModule_config.dynamicResourcesEnginePath + '/registry/dependentColumnsDialog.tpl.html', locals: { dontShowAgain: $scope.stopShow, - columns: $scope.dependentColumns + columns: $scope.joinedFields }, targetEvent: event, clickOutsideToClose: false, @@ -413,8 +452,24 @@ fullscreen: true } ); + }; - + + $scope.emptyDependentColumns = function (dependentColumns) { + + for (var i = 0; i < $scope.selectedRow.length; i++) { + + for(var property in $scope.selectedRow[i]) { + + for (var k in dependentColumns) { + if (angular.equals(dependentColumns[k].field, property)) { + $scope.selectedRow[i][property] = ''; + } + } + } + } + } + function DialogController($scope, $mdDialog, dontShowAgain, columns, sbiModule_translate) { $scope.dontShowAgain = dontShowAgain; $scope.dependentColumns = columns; @@ -443,6 +498,19 @@ }); }; + $scope.checkIfFiltersHaveValues = function() { + for (var i = 0; i < registryConfiguration.filters.length; i++) { + var filter = registryConfiguration.filters[i]; + for (var j = 0; j < registryConfiguration.columns.length; j++) { + var column = registryConfiguration.columns[j]; + if(filter.presentation != 'DRIVER' && filter.field == column.field){ + if(filter.value) return true; + } + } + } + return false; + } + $scope.checkIfFilterColumnExists = function(){ var filters = []; for (var i = 0; i < registryConfiguration.filters.length; i++) { @@ -484,7 +552,12 @@ } loadInitialData($scope.formParams); }; - + + $scope.resetDateField = function (e, row, col) { + e.preventDefault(); + row[col.field] = null; + } + // Update $scope.setSelected = function(selectedRow) { @@ -501,35 +574,35 @@ $scope.selectedRow[i][property].setTime($scope.selectedRow[i][property].getTime() - new Date().getTimezoneOffset()*60*1000); } } - registryCRUD.update($scope.selectedRow[i]).then(function(response) { - sbiMessaging.showInfoMessage( $scope.sbiTranslate.load("kn.registry.registryDocument.update.success") - +' '+ (response.data.ids.length) + ' ' + $scope.sbiTranslate.load("kn.registry.registryDocument.row"), $scope.sbiTranslate.load("kn.registry.registryDocument.success")); - $scope.selectedRow = []; - }); + } + registryCRUD.update($scope.selectedRow).then(function(response) { + readData($scope.formParams); + sbiMessaging.showInfoMessage( $scope.sbiTranslate.load("kn.registry.registryDocument.update.success") + +' '+ ($scope.selectedRow.length) + ' ' + $scope.sbiTranslate.load("kn.registry.registryDocument.row"), $scope.sbiTranslate.load("kn.registry.registryDocument.success")); + $scope.selectedRow.length = 0; + }); }; // Delete $scope.deleteRowFromDB = function(row, event) { - if(row.id) { - var confirm = $mdDialog.confirm() - .title(sbiModule_translate.load('kn.registry.document.delete.row')) - .textContent(sbiModule_translate.load('kn.registry.document.delete.confirm.message')) - .targetEvent(event) - .ok(sbiModule_translate.load('kn.qbe.general.yes')) - .cancel(sbiModule_translate.load('kn.qbe.general.no')); - - $mdDialog.show(confirm).then(function() { - registryCRUD.delete(row).then(function(response) { - sbiMessaging.showInfoMessage($scope.sbiTranslate.load("kn.registry.registryDocument.delete.success"), $scope.sbiTranslate.load("kn.registry.registryDocument.success")); - $scope.deleteRow(row.$$hashKey); - }); + + var confirm = $mdDialog.confirm() + .title(sbiModule_translate.load('kn.registry.document.delete.row')) + .textContent(sbiModule_translate.load('kn.registry.document.delete.confirm.message')) + .targetEvent(event) + .ok(sbiModule_translate.load('kn.qbe.general.yes')) + .cancel(sbiModule_translate.load('kn.qbe.general.no')); + + $mdDialog.show(confirm).then(function() { + registryCRUD.delete(row).then(function(response) { + sbiMessaging.showInfoMessage($scope.sbiTranslate.load("kn.registry.registryDocument.delete.success"), $scope.sbiTranslate.load("kn.registry.registryDocument.success")); + $scope.deleteRow(row.$$hashKey); }); - } else { - $scope.deleteRow(row.$$hashKey); - } + }); + }; @@ -599,6 +672,16 @@ $scope.formParams = pagination.previous($scope.page,$scope.formParams,$scope.configuration.itemsPerPage,$scope.filters); readData($scope.formParams); }; + $scope.last = function() { + $scope.page= $scope.getTotalPages.length; + $scope.formParams = pagination.previous($scope.page,$scope.formParams,$scope.configuration.itemsPerPage,$scope.filters); + readData($scope.formParams); + }; + $scope.first = function() { + $scope.page= 1; + $scope.formParams = pagination.previous($scope.page,$scope.formParams,$scope.configuration.itemsPerPage,$scope.filters); + readData($scope.formParams); + } $scope.goToPage = function() { $scope.formParams = pagination.goToPage($scope.page,$scope.formParams,$scope.configuration.itemsPerPage,$scope.filters); readData($scope.formParams); @@ -616,7 +699,7 @@ var namesOfDateColumns =[]; for(var i = 0 ; i - -
-

{{configuration.title}}

-
-
- -
-
-
- Clear - -
- - - - - - {{opt.column_1}} - - -
- Filter - -
-
- Save - -
-
-
-
- - - - - - - - - - - - + + +
  -
- {{col.title}} - {{col.title}} - - - - - - - - - Move Left - - - - - - Move Right - - - - -
-
- - Add row - -
{{$index+1}} -
- {{row[col.field] }} - - - -
- {{row[col.field] | number}} - {{row[col.field]}} - {{row[col.field] | date:"MM/dd/yyyy"}} - {{row[col.field]}} - {{row[col.field]}} - {{row[col.field] | decimal:col.format}} +
+ +
+

{{configuration.title}}

+ + + Save + +
+
+ + + + Filters +
+ + + + + + {{opt.column_1}} + + + + + Clear + Clear all filters + + + Filter + +
+
+ + + + + + + + + + + + + + - - - -
  +
+ {{col.title}} + {{col.title}} + + + + + + + + + + Move Left + + + + + + Move Right + + + + +
+
+ + + Add Row + +
{{$index+1}} +
+ {{row[col.field] }} + + + +
+ {{row[col.field] | number}} + {{row[col.field]}} + {{row[col.field] | momentDate:currLanguage}} + {{row[col.field]}} + {{row[col.field]}} + {{row[col.field] | decimal:col.format}} +
+ + + +
+ +
+ + {{opt.column_1}} + +
+
+ + {{opt.column_1}} + +
+
+
+ +
- - - - -
- - {{opt.column_1}} - -
-
- - {{opt.column_1}} - -
-
-
-
-
-
-
- -
- - - - - - - - - - + + + +
-
- {{col.title}} - -
-
-
- {{row[col.field] }} - {{row[col.field] | number:getDecimalPlaces(col.field) }} - - - -
- {{row[col.field] | number}} - {{row[col.field] | date:"MM/dd/yyyy"}} - {{row[col.field]}} - {{row[col.field] | decimal:col.format}} + + + + +
+
+ +
+ + + + + + + + + - - -
+
+ {{col.title}} + +
+
+
+ {{row[col.field] }} + {{row[col.field] | number:getDecimalPlaces(col.field) }} + + + +
+ {{row[col.field] | number}} + {{row[col.field] | momentDate:currLanguage}} + {{row[col.field]}} + {{row[col.field] | decimal:col.format}} +
+ + + +
+ +
+ + {{opt.column_1}} + +
+
+ + {{opt.column_1}} + +
- - - - -
- - {{opt.column_1}} - -
-
- - {{opt.column_1}} - -
-
-
-
-
-
-
- -
- -
+
+ + +
+ + + +
+
+
+
+
+
+ + {{min}} to {{max}} of {{resultsNumber}} + + +
+ +
+
+ +
+ Page {{page}} of {{getTotalPages.length}} +
+ +
+
+ +
+
+
+
+
+ + +
\ No newline at end of file diff --git a/knowageqbeengine/src/main/webapp/js/src/registry/services/interceptors/httpInterceptor.js b/knowageqbeengine/src/main/webapp/js/src/registry/services/interceptors/httpInterceptor.js index 7c318dbd882..c64f2d99aa3 100644 --- a/knowageqbeengine/src/main/webapp/js/src/registry/services/interceptors/httpInterceptor.js +++ b/knowageqbeengine/src/main/webapp/js/src/registry/services/interceptors/httpInterceptor.js @@ -26,7 +26,7 @@ return { 'responseError': function(rejection) { var sbiMsg = $injector.get('sbiModule_messaging'); - var msg = sbiMsg.showErrorMessage(rejection.data.errors[0].message, 'Failure!!!'); + var msg = sbiMsg.showErrorMessage(rejection.data.errors[0].message, 'Error'); return $q.reject(msg); } } diff --git a/knowageqbeengine/src/main/webapp/js/src/registry/services/registryCRUDService.js b/knowageqbeengine/src/main/webapp/js/src/registry/services/registryCRUDService.js index 72481f3504a..c94e4c45e3f 100644 --- a/knowageqbeengine/src/main/webapp/js/src/registry/services/registryCRUDService.js +++ b/knowageqbeengine/src/main/webapp/js/src/registry/services/registryCRUDService.js @@ -30,20 +30,20 @@ return promise; }; - crud.update = function(record) { + crud.update = function(records) { //delete record.id; - delete record.selected; - var records = []; + for (var i = 0; i < records.length; i++) { + delete records[i].selected; + + } var loadRegistryAction = this.action.getActionBuilder('POST'); loadRegistryAction.actionName = 'UPDATE_RECORDS_ACTION'; loadRegistryAction.formParams.records = records; - loadRegistryAction.formParams.records.push(record); var promise = loadRegistryAction.executeAction(); return promise; }; crud.delete = function(record) { - delete record.id; var records = []; var loadRegistryAction = this.action.getActionBuilder('POST'); loadRegistryAction.actionName = 'DELETE_RECORDS_ACTION'; diff --git a/knowagesvgviewerengine/src/main/java/it/eng/knowage/engines/svgviewer/api/restful/SvgViewerResource.java b/knowagesvgviewerengine/src/main/java/it/eng/knowage/engines/svgviewer/api/restful/SvgViewerResource.java index dea27f72628..7e516c7554d 100644 --- a/knowagesvgviewerengine/src/main/java/it/eng/knowage/engines/svgviewer/api/restful/SvgViewerResource.java +++ b/knowagesvgviewerengine/src/main/java/it/eng/knowage/engines/svgviewer/api/restful/SvgViewerResource.java @@ -48,7 +48,9 @@ import java.util.Map; import java.util.Properties; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; @@ -69,9 +71,9 @@ public class SvgViewerResource extends AbstractSvgViewerEngineResource { @Path("/drawMap") - @GET + @POST @Produces({ MediaType.APPLICATION_SVG_XML, MediaType.APPLICATION_JSON }) - public Response drawMap(@QueryParam("level") String level) { + public Response drawMap(@FormParam("level") String level) { logger.debug("IN"); try { // SourceBean savedTemplate = getTemplateAsSourceBean(); @@ -107,9 +109,9 @@ public Response drawMap(@QueryParam("level") String level) { * @return */ @Path("/getMeasures") - @GET + @POST @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getMeasures(@QueryParam("level") String level) { + public Response getMeasures(@FormParam("level") String level) { logger.debug("IN"); try { SourceBean memberSB = getActiveMemberSB(level); @@ -135,9 +137,9 @@ public Response getMeasures(@QueryParam("level") String level) { * @return */ @Path("/getLayers") - @GET + @POST @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getLayers(@QueryParam("level") String level) { + public Response getLayers(@FormParam("level") String level) { logger.debug("IN"); try { SourceBean memberSB = getActiveMemberSB(level); @@ -157,10 +159,10 @@ public Response getLayers(@QueryParam("level") String level) { } @Path("/drillMap") - @GET + @POST @Produces(SvgViewerEngineConstants.SVG_MIME_TYPE + "; charset=UTF-8") - public Response drillMap(@QueryParam("document") String documentId, @QueryParam("level") String level, @QueryParam("member") String member, - @QueryParam("parent") String parent) { + public Response drillMap(@FormParam("document") String documentId, @FormParam("level") String level, @FormParam("member") String member, + @FormParam("parent") String parent) { logger.debug("IN"); try { // 0. Define internal objects @@ -236,9 +238,9 @@ public Response drillMap(@QueryParam("document") String documentId, @QueryParam( * @return */ @Path("/getCustomizedConfiguration") - @GET + @POST @Produces(MediaType.APPLICATION_JSON + "; charset=UTF-8") - public Response getCustomizedConfiguration(@QueryParam("level") String level) { + public Response getCustomizedConfiguration(@FormParam("level") String level) { logger.debug("IN"); try { // SourceBean savedTemplate = getTemplateAsSourceBean(); diff --git a/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java b/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java new file mode 100644 index 00000000000..edf35e4310f --- /dev/null +++ b/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/MetadataDatabaseConfigurationRetriever.java @@ -0,0 +1,62 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.commons; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.bo.Config; +import it.eng.spagobi.commons.dao.DAOFactory; +import it.eng.spagobi.commons.dao.IConfigDAO; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own implementation. The engines may have + * different implementations. + * + * @author Andrea Gioia (andrea.gioia@eng.it) + * + */ +public class MetadataDatabaseConfigurationRetriever implements IConfigurationRetriever { + + private static Logger logger = Logger.getLogger(MetadataDatabaseConfigurationRetriever.class); + + public MetadataDatabaseConfigurationRetriever() { + } + + @Override + public String get(String key) { + String toReturn = null; + try { + IConfigDAO dao = DAOFactory.getSbiConfigDAO(); + Config config = dao.loadConfigParametersByLabel(key); + if (config != null) { + toReturn = config.getValueCheck(); + } + } catch (Exception e) { + throw new SpagoBIRuntimeException("An error occurred while getting configuration with label [" + key + "]", e); + } + + if (toReturn == null) { + logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); + return null; + } + logger.debug("GET :" + key + "=" + toReturn); + return toReturn; + } + +} diff --git a/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java b/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java deleted file mode 100644 index 8bc0074eba4..00000000000 --- a/knowagesvgviewerengine/src/main/java/it/eng/spagobi/commons/SingletonConfigCache.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.commons; - -import it.eng.spagobi.commons.bo.Config; -import it.eng.spagobi.commons.dao.DAOFactory; -import it.eng.spagobi.commons.dao.IConfigDAO; - -import java.util.HashMap; -import java.util.List; - -import org.apache.log4j.Logger; - -/** - * This object is instantiated and used by SingletonConfig to read config parameters. SpagoBi project have its own iplementation. The engines have different - * implementation. - * - * @author Andrea Gioia (andrea.gioia@eng.it) - * - */ -public class SingletonConfigCache implements ISingletonConfigCache{ - - private static Logger logger = Logger.getLogger(SingletonConfigCache.class); - private final HashMap cache=new HashMap(); - - public SingletonConfigCache() { - logger.debug("IN"); - - IConfigDAO dao = null; - try { - dao = DAOFactory.getSbiConfigDAO(); - List allConfig = dao.loadAllConfigParameters(); - if (allConfig.isEmpty()) { - logger.error("The table sbi_config is EMPTY"); - } - for (Config config: allConfig ) { - cache.put(config.getLabel(), config.getValueCheck()); - logger.info("Add: "+config.getLabel() +" / "+config.getValueCheck()); - } - - } catch (Throwable e) { - logger.error("Impossible to load configuration for report engine",e); - } finally { - logger.debug("OUT"); - } - } - - /** - * TODO : Workaround for KNOWAGE-4784 - */ - @Override - public String get(String key) { - String ret = null; - try { - IConfigDAO dao = null; - dao = DAOFactory.getSbiConfigDAO(); - ret = dao.loadConfigParametersByLabel(key).getValueCheck(); - } catch (Exception e) { - } - - if (/* cache.get(key) */ ret == null) { - logger.info("The property '" + key + "' doens't have any value assigned, check SBI_CONFIG table"); - return null; - } - logger.debug("GET :" + key + "=" + /*cache.get(key)*/ ret); - return /*cache.get(key)*/ ret; - } - -} diff --git a/knowagesvgviewerengine/src/main/webapp/META-INF/context.xml b/knowagesvgviewerengine/src/main/webapp/META-INF/context.xml index da598aa42b1..42011fc7400 100644 --- a/knowagesvgviewerengine/src/main/webapp/META-INF/context.xml +++ b/knowagesvgviewerengine/src/main/webapp/META-INF/context.xml @@ -9,4 +9,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index 8ccc021d708..d871ea90dc5 100644 --- a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -45,5 +45,7 @@ +"/> + <%@include file="/WEB-INF/jsp/commons/angular/sbiModule.jsp"%> \ No newline at end of file diff --git a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf index aaac3000d18..f7204661ad6 100644 --- a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf +++ b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf @@ -17,12 +17,15 @@ <%@page import="java.util.ArrayList"%> <%@page import="java.util.Map"%> <%@page import="it.eng.knowage.engines.svgviewer.SvgViewerEngineInstance"%> +<%@page import="it.eng.spagobi.commons.utilities.GeneralUtilities"%> <%@page import="it.eng.spagobi.utilities.engines.EngineConstants"%> <%@page import="java.util.Iterator"%> <%@page import="it.eng.spagobi.commons.constants.SpagoBIConstants"%> <%@page import="java.util.HashMap"%> <%@page import="org.json.JSONObject"%> <%@page import="org.json.JSONArray"%> +<%@page import="it.eng.knowage.commons.utilities.urls.UrlBuilder"%> +<%@page import="com.fasterxml.jackson.databind.ObjectMapper"%> <%-- ---------------------------------------------------------------------- --%> <%-- JAVA CODE --%> @@ -58,6 +61,10 @@ engineInstance = (SvgViewerEngineInstance)request.getSession().getAttribute(EngineConstants.ENGINE_INSTANCE); env = engineInstance.getEnv(); locale = engineInstance.getLocale(); + + String spagoBiContext = GeneralUtilities.getSpagoBiContext(); // /knowage + String svgEngineContext = request.getContextPath(); + UrlBuilder urlBuilder = new UrlBuilder(spagoBiContext, svgEngineContext); executionRole = (String)env.get(EngineConstants.ENV_EXECUTION_ROLE); executionID = (String)env.get("SBI_EXECUTION_ID"); diff --git a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/svgViewerImport.jsp b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/svgViewerImport.jsp index b1baf4ad49f..8678a060ef0 100644 --- a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/svgViewerImport.jsp +++ b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/commons/angular/svgViewerImport.jsp @@ -1,4 +1,3 @@ - <%@include file="/WEB-INF/jsp/commons/angular/svgViewerResource.jsp"%> diff --git a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/svgViewer.jsp b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/svgViewer.jsp index 16254f05934..91ac785b5bc 100644 --- a/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/svgViewer.jsp +++ b/knowagesvgviewerengine/src/main/webapp/WEB-INF/jsp/svgViewer.jsp @@ -31,21 +31,18 @@ <%@include file="/WEB-INF/jsp/commons/angular/svgViewerImport.jsp"%> + <% if (isCustomizedSVG) {%> <%-- This is because dynamicSvg.js is plain javascript, and it is impossible to get the angular scope ---------------- --%> - <% } %> - SVG Viewer -
+
<% if (isCustomizedSVG) {%><% }else{ %> <% } %> @@ -121,10 +118,7 @@
- + <% if (isCustomizedSVG) {%>
diff --git a/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/directives/dynamicSvg.js b/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/directives/dynamicSvg.js index bad1b29bda7..bbfb2dfe319 100644 --- a/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/directives/dynamicSvg.js +++ b/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/directives/dynamicSvg.js @@ -18,8 +18,9 @@ function createChart() { function serviceGetData() { var jqxhr = $.ajax({ - url: '/knowagesvgviewerengine/api/1.0/svgviewer/getCustomizedConfiguration?'+requestQueryString, - type: 'get', + url: '/knowagesvgviewerengine/api/1.0/svgviewer/getCustomizedConfiguration', + type: 'post', + body: _requestParameterMap }) .done(function(response) { serviceResponse = response.data; diff --git a/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/svgViewerController.js b/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/svgViewerController.js index 82e7caed153..de1d93e410a 100644 --- a/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/svgViewerController.js +++ b/knowagesvgviewerengine/src/main/webapp/js/src/angular_1.x/svgviewer/svgViewerController.js @@ -28,6 +28,45 @@ app.controller('SvgViewerController', ['$scope','sbiModule_restServices','$mdSidenav','sbiModule_logger','$window','sbiModule_config','$rootScope','$sce','$timeout',SvgViewerControllerFunction] ); function SvgViewerControllerFunction($scope, sbiModule_restServices, $mdSidenav,sbiModule_logger,$window,sbiModule_config,$rootScope,$sce,$timeout) { + + //hidden Iframe initialization + $scope.requestParameterMap = _requestParameterMap; + function createForm(){ + + var svgForm = document.createElement("form"); + svgForm.id="svgForm"; + svgForm.action = sbiModule_config.contextName + "/api/1.0/svgviewer/drawMap"; + svgForm.method = "post"; + svgForm.target = "svgContainer"; + document.body.appendChild(svgForm); + + for (var k in $scope.requestParameterMap) { + var element = document.createElement("input"); + element.type = "hidden"; + element.id= 'svgForm_' + k; + element.name = k; + element.value = $scope.requestParameterMap[k]; + svgForm.appendChild(element); + } + svgForm.submit(); + } + createForm(); + + function submitForm(){ + document.getElementById("svgForm").submit(); + } + + function updateForm(property,value){ + var inputElement = document.getElementById("svgForm_" + property); + if(!inputElement) { + inputElement = document.createElement("input"); + inputElement.type = "hidden"; + inputElement.id= 'svgForm_' + property; + inputElement.name = property; + document.getElementById("svgForm").appendChild(inputElement); + } + inputElement.value = value; + } $scope.showBackButton = false; //initialize for the first level @@ -69,14 +108,17 @@ function SvgViewerControllerFunction($scope, sbiModule_restServices, $mdSidenav, $scope.env = pathElement.env; if (pathElement.level == 1){ - document.getElementById('svgContainer').src = sbiModule_config.contextName+"/api/1.0/svgviewer/drillMap?document="+pathElement.document+"&level="+pathElement.level+pathElement.env; + updateForm('level',pathElement.level+pathElement.env); + updateForm('document',pathElement.document); } else { - var urlToCall = sbiModule_config.contextName+"/api/1.0/svgviewer/drillMap?document="+pathElement.document+"&member="+pathElement.member+"&level="+pathElement.level+pathElement.env; + updateForm('level',pathElement.level+pathElement.env); + updateForm('member',pathElement.member); + updateForm('document',pathElement.document); if (pathElement.parent != undefined && pathElement.parent != null){ - urlToCall = urlToCall + "&parent=" + pathElement.parent; + updateForm('parent',pathElement.parent); } - document.getElementById('svgContainer').src = urlToCall; } + submitForm(); if($scope.currentLevel == 1){ $scope.showBackButton = false; @@ -122,8 +164,11 @@ function SvgViewerControllerFunction($scope, sbiModule_restServices, $mdSidenav, $scope.currentParent = e.detail.idElement; $scope.document = e.detail.document; $scope.env = e.detail.env; - document.getElementById('svgContainer').src = sbiModule_config.contextName+"/api/1.0/svgviewer/drillMap?"+$scope.requestQueryString+"&member="+$scope.currentMember+"&level="+$scope.currentLevel+"&parent="+$scope.currentParent+"&document="+$scope.document+$scope.env; - + updateForm('level',$scope.currentLevel); + updateForm('document',$scope.document+$scope.env); + updateForm('member',$scope.currentMember); + updateForm('parent',$scope.currentParent); + submitForm(); if ($scope.currentLevel > 1){ $scope.showBackButton = true; @@ -222,22 +267,24 @@ function SvgViewerControllerFunction($scope, sbiModule_restServices, $mdSidenav, * Loads the measures list with a REST service * */ $scope.getMeasures = function(){ - sbiModule_restServices.get("1.0/svgviewer", 'getMeasures',$scope.requestQueryString+'&level='+$scope.currentLevel).success( - function(data, status, headers, config) { - if (data.hasOwnProperty("errors")) { + var parametersClone = angular.copy($scope.requestParameterMap); + parametersClone.level = $scope.currentLevel; + sbiModule_restServices.post("1.0/svgviewer", 'getMeasures', parametersClone).then( + function(response) { + if (response.data.hasOwnProperty("errors")) { sbiModule_logger.log("measures not retrivied"); } else { - $scope.measures = data; + $scope.measures = response.data; for (var propt in $scope.measures){ if ($scope.measures[propt].selected){ //set default selected measure $scope.measureValue = $scope.measures[propt].columnId; } } - sbiModule_logger.trace("measures correctly retrivied",data); + sbiModule_logger.trace("measures correctly retrieved",response.data); } - }).error(function(data, status, headers, config) { - sbiModule_logger.log("measures not retrivied"); + },function(error) { + sbiModule_logger.log("measures not retrieved"); }); }; @@ -253,22 +300,24 @@ function SvgViewerControllerFunction($scope, sbiModule_restServices, $mdSidenav, * Loads the measures list with a REST service * */ $scope.getLayers = function(){ - sbiModule_restServices.get("1.0/svgviewer", 'getLayers',$scope.requestQueryString+'&level='+$scope.currentLevel).success( - function(data, status, headers, config) { - if (data.hasOwnProperty("errors")) { - sbiModule_logger.log("layers not retrivied"); + var parametersClone = angular.copy($scope.requestParameterMap); + parametersClone.level = $scope.currentLevel; + sbiModule_restServices.post("1.0/svgviewer", 'getLayers',parametersClone).then( + function(response) { + if (response.data.hasOwnProperty("errors")) { + sbiModule_logger.log("layers not retrieved"); } else { - for (var key in data) { + for (var key in response.data) { //force all layers to be selected by default data[key].selected = true; } - $scope.layers = data; - sbiModule_logger.trace("layers correctly retrivied",data); + $scope.layers = response.data; + sbiModule_logger.trace("layers correctly retrieved",response.data); } - }).error(function(data, status, headers, config) { - sbiModule_logger.log("layers not retrivied"); + },function(error) { + sbiModule_logger.log("layers not retrieved"); }); }; diff --git a/knowagetalendengine/src/main/webapp/META-INF/context.xml b/knowagetalendengine/src/main/webapp/META-INF/context.xml index c1225a96b0e..79620c72f05 100644 --- a/knowagetalendengine/src/main/webapp/META-INF/context.xml +++ b/knowagetalendengine/src/main/webapp/META-INF/context.xml @@ -8,5 +8,5 @@ - - + + diff --git a/knowageutils/pom.xml b/knowageutils/pom.xml index bdb07e1aaa3..651b7cdf6ea 100644 --- a/knowageutils/pom.xml +++ b/knowageutils/pom.xml @@ -285,7 +285,7 @@ com.jayway.jsonpath json-path - 2.0.0 + 2.4.0 compile @@ -634,6 +634,38 @@ 2.2.4 + + mysql + mysql-connector-java + 5.1.47 + test + + + + + com.amazon.redshift + redshift-jdbc42 + 1.2.37.1061 + test + + + + + com.amazon.redshift + redshift-jdbc4 + 1.2.10.1009 + test + + + + + com.github.noraui + ojdbc7 + 12.1.0.2 + provided + + + \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/knowage/mail/MailSessionBuilder.java b/knowageutils/src/main/java/it/eng/knowage/mail/MailSessionBuilder.java new file mode 100644 index 00000000000..3fb93a84829 --- /dev/null +++ b/knowageutils/src/main/java/it/eng/knowage/mail/MailSessionBuilder.java @@ -0,0 +1,397 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2020 Engineering Ingegneria Informatica S.p.A. + + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + + * Knowage 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 Affero General Public License for more details. + + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.knowage.mail; + +import java.security.Security; +import java.util.Properties; + +import javax.mail.Address; +import javax.mail.Authenticator; +import javax.mail.Message; +import javax.mail.MessagingException; +import javax.mail.NoSuchProviderException; +import javax.mail.PasswordAuthentication; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; + +import org.apache.commons.lang3.StringUtils; +import org.apache.log4j.LogMF; +import org.apache.log4j.Logger; + +import it.eng.spagobi.commons.SingletonConfig; +import it.eng.spagobi.commons.utilities.StringUtilities; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * Build a new {@link Session} to send email. + * + * @author Marco Libanori + */ +public class MailSessionBuilder { + + private static Logger logger = Logger.getLogger(MailSessionBuilder.class); + + /** + * Define the supported security modes. + */ + private static enum SecurityMode { + NONE(25), + SSL(465), + STARTTLS(587); + + private final int defaultPort; + + private SecurityMode(int defaultPort) { + this.defaultPort = defaultPort; + } + + /** + * @return the defaultPort + */ + public int getDefaultPort() { + return defaultPort; + } + } + + private class SMTPAuthenticator extends javax.mail.Authenticator { + private String username = ""; + private String password = ""; + + @Override + public PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + + public SMTPAuthenticator(String user, String pass) { + this.username = user; + this.password = pass; + } + } + + /** + * Facade for {@link Session} object. + * + * It simplifies the contract to get only the needed methods. + */ + public static class SessionFacade { + + private final Session session; + private final InternetAddress from; + private final SecurityMode securityMode; + private final String host; + private final int port; + private final String user; + private final String password; + + private SessionFacade(Session session, InternetAddress from, SecurityMode securityMode, String host, int port, String user, String password) { + this.session = session; + this.from = from; + this.securityMode = securityMode; + this.host = host; + this.port = port; + this.user = user; + this.password = password; + } + + public Transport getTransport() throws NoSuchProviderException { + if (securityMode == SecurityMode.SSL) { + return session.getTransport("smtps"); + } else { + return session.getTransport("smtp"); + } + } + + public Message createNewMimeMessage() throws MessagingException { + MimeMessage ret = new MimeMessage(session); + ret.setFrom(from); + return ret; + } + + public void sendMessage(Message message) throws NoSuchProviderException, MessagingException { + Transport transport = null; + Address[] allRecipients = null; + try { + allRecipients = message.getAllRecipients(); + + transport = getTransport(); + if (securityMode == SecurityMode.SSL) { + transport.connect(host, port, user, password); + } else { + transport.connect(); + } + transport.sendMessage(message, allRecipients); + } catch (Exception e) { + Properties properties = session.getProperties(); + LogMF.error(logger, e, "Error sending email with a session having properties {0}", new String[] { String.valueOf(properties) }); + throw e; + } finally { + if (transport != null) { + try { + transport.close(); + } catch (Exception e) { + // Yes, it's muted! + } + } + } + } + } + + private static final String DEFAULT_SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; + private static final String CUSTOM_SSL_FACTORY = "it.eng.spagobi.commons.services.DummySSLSocketFactory"; + + private static final String SMTP_HOST_TEMPLATE = "MAIL.PROFILES.%s.smtphost"; + private static final String SMTP_PORT_TEMPLATE = "MAIL.PROFILES.%s.smtpport"; + private static final String FROM_TEMPLATE = "MAIL.PROFILES.%s.from"; + private static final String USER_TEMPLATE = "MAIL.PROFILES.%s.user"; + private static final String PASSWORD_TEMPLATE = "MAIL.PROFILES.%s.password"; + private static final String SECURITY_TEMPLATE = "MAIL.PROFILES.%s.security"; + + private final String trustedStoreFileKey = "MAIL.PROFILES.trustedStore.file"; + + private final String trustedStoreFileValue; + private String smtpHostValue; + private String smtpPortValue; + private String fromValue; + private String userValue; + private String passwordValue; + private String securityValue; + private String profileName; + private Integer timeout; + private Integer connectionTimeout; + + private MailSessionBuilder() { + SingletonConfig config = SingletonConfig.getInstance(); + + trustedStoreFileValue = config.getConfigValue(trustedStoreFileKey); + } + + /** + * @return This builder + */ + public static MailSessionBuilder newInstance() { + return new MailSessionBuilder(); + } + + /** + * @return This builder + */ + public MailSessionBuilder usingSchedulerProfile() { + return usingProfile("scheduler"); + } + + /** + * @return This builder + */ + public MailSessionBuilder usingUserProfile() { + return usingProfile("user"); + } + + /** + * @return This builder + */ + public MailSessionBuilder usingKpiAlarmProfile() { + return usingProfile("kpi_alarm"); + } + + /** + * Use specific profile name, defined in the configuration. + * + * @param profileName Name of the profile + * @return This builder + */ + public MailSessionBuilder usingProfile(String profileName) { + + if (StringUtils.isEmpty(profileName)) { + throw new SpagoBIRuntimeException("Email's profile name cannot be empty"); + } + this.profileName = profileName; + + LogMF.info(logger, "Using profile name {0}", profileName); + + String smtpHostKey = String.format(SMTP_HOST_TEMPLATE, profileName); + String smtpPortKey = String.format(SMTP_PORT_TEMPLATE, profileName); + String fromKey = String.format(FROM_TEMPLATE, profileName); + String userKey = String.format(USER_TEMPLATE, profileName); + String passwordKey = String.format(PASSWORD_TEMPLATE, profileName); + String securityKey = String.format(SECURITY_TEMPLATE, profileName); + + logger.debug("We got the following profile keys:"); + LogMF.debug(logger, "\tsmtpHostKey = {0}", smtpHostKey); + LogMF.debug(logger, "\tsmtpPortKey = {0}", smtpPortKey); + LogMF.debug(logger, "\tfromKey = {0}", fromKey ); + LogMF.debug(logger, "\tuserKey = {0}", userKey ); + LogMF.debug(logger, "\tpasswordKey = {0}", passwordKey); + LogMF.debug(logger, "\tsecurityKey = {0}", securityKey); + + SingletonConfig config = SingletonConfig.getInstance(); + + smtpHostValue = config.getConfigValue(smtpHostKey); + smtpPortValue = config.getConfigValue(smtpPortKey); + fromValue = config.getConfigValue(fromKey); + userValue = config.getConfigValue(userKey); + passwordValue = config.getConfigValue(passwordKey); + securityValue = config.getConfigValue(securityKey); + + logger.debug("We got the following profile values:"); + LogMF.debug(logger, "\tsmtpHostValue = {0}", smtpHostValue); + LogMF.debug(logger, "\tsmtpPortValue = {0}", smtpPortValue); + LogMF.debug(logger, "\tfromValue = {0}", fromValue ); + LogMF.debug(logger, "\tuserValue = {0}", userValue ); + LogMF.debug(logger, "\tpasswordValue = {0}", passwordValue); + LogMF.debug(logger, "\tsecurityValue = {0}", securityValue); + + return this; + } + + public SessionFacade build() throws AddressException { + + Session session = null; + + Properties props = new Properties(); + + LogMF.info(logger, "Creating a new SessionFacade for profile name {0}", profileName); + + SecurityMode securityValueEnum = SecurityMode.valueOf(securityValue); + if (securityValueEnum == null) { + securityValueEnum = SecurityMode.NONE; + } + if (securityValueEnum == SecurityMode.NONE) { + props.put("mail.smtp.starttls.enable", "false"); + } else if (securityValueEnum == SecurityMode.SSL) { + props.put("mail.smtp.starttls.enable", "false"); + } else if (securityValueEnum == SecurityMode.STARTTLS) { + props.put("mail.smtp.starttls.enable", "true"); + } + + + props.put("mail.smtp.host", smtpHostValue); + + + if (StringUtils.isEmpty(smtpPortValue)) { + int defaultPort = securityValueEnum.getDefaultPort(); + + LogMF.warn(logger, "SMTP port is empty: using the default port {0}", defaultPort); + smtpPortValue = Integer.toString(defaultPort); + } + props.put("mail.smtp.port", smtpPortValue); + + + Authenticator auth = null; + if (StringUtils.isNotEmpty(userValue)) { + props.put("mail.smtp.user", userValue); + props.put("mail.smtp.password", passwordValue); + } + + + if (StringUtils.isEmpty(fromValue)) { + fromValue = "spagobi.scheduler@eng.it"; + } + InternetAddress fromValueInternetAddress = new InternetAddress(fromValue); + props.put("mail.smtp.from", fromValue); + + + if (timeout != null) { + props.put("mail.smtp.timeout", timeout.toString()); + } + + + if (connectionTimeout != null) { + props.put("mail.smtp.connectiontimeout", connectionTimeout.toString()); + } + + + // create autheticator object + if (StringUtils.isNotEmpty(userValue)) { + auth = new SMTPAuthenticator(userValue, passwordValue); + props.put("mail.smtp.auth", "true"); + // SSL Connection + if (securityValueEnum == SecurityMode.SSL) { + Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); + props.put("mail.smtps.auth", "true"); + props.put("mail.smtps.socketFactory.port", smtpPortValue); + if ((!StringUtilities.isEmpty(trustedStoreFileValue))) { + props.put("mail.smtps.socketFactory.class", CUSTOM_SSL_FACTORY); + + } else { + props.put("mail.smtps.socketFactory.class", DEFAULT_SSL_FACTORY); + } + props.put("mail.smtp.socketFactory.fallback", "false"); + } + session = Session.getInstance(props, auth); + } else { + session = Session.getInstance(props); + } + + + // TODO Debug??? + // session.setDebug(true); + // session.setDebugOut(System.out); + + + LogMF.debug(logger, "Session created using properties {0}", props); + LogMF.info(logger, "End creating a new SessionFacade for profile name {0}", profileName); + + return new SessionFacade(session, fromValueInternetAddress, securityValueEnum, smtpHostValue, Integer.parseInt(smtpPortValue), userValue, passwordValue); + } + + public MailSessionBuilder withTimeout(int timeout) { + this.timeout = timeout; + + return this; + } + + public MailSessionBuilder withConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + + return this; + } + + public MailSessionBuilder overwritingFromAddress(String fromValue) { + if (StringUtils.isNotEmpty(fromValue)) { + logger.warn("Overwriting the from address..."); + LogMF.debug(logger, "... with {0} replacing {1}", fromValue, this.fromValue); + this.fromValue = fromValue; + } + + return this; + } + + public MailSessionBuilder overwritingUser(String userValue) { + if (StringUtils.isNotEmpty(userValue)) { + logger.warn("Overwriting the username..."); + LogMF.debug(logger, "... with {0} replacing {1}", userValue, this.userValue); + this.userValue = userValue; + } + + return this; + } + + public MailSessionBuilder overwritingPassword(String passwordValue) { + if (StringUtils.isNotEmpty(passwordValue)) { + logger.warn("Overwriting the password..."); + LogMF.debug(logger, "... with {0} replacing {1}", passwordValue, this.passwordValue); + this.passwordValue = passwordValue; + } + + return this; + } +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/ISingletonConfigCache.java b/knowageutils/src/main/java/it/eng/spagobi/commons/IConfigurationRetriever.java similarity index 95% rename from knowageutils/src/main/java/it/eng/spagobi/commons/ISingletonConfigCache.java rename to knowageutils/src/main/java/it/eng/spagobi/commons/IConfigurationRetriever.java index 22b39cb36cf..1e20f385b1f 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/ISingletonConfigCache.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/IConfigurationRetriever.java @@ -17,6 +17,6 @@ */ package it.eng.spagobi.commons; -public interface ISingletonConfigCache { +public interface IConfigurationRetriever { String get(String key); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/SimpleSingletonConfigCache.java b/knowageutils/src/main/java/it/eng/spagobi/commons/SimpleConfigurationRetriever.java similarity index 92% rename from knowageutils/src/main/java/it/eng/spagobi/commons/SimpleSingletonConfigCache.java rename to knowageutils/src/main/java/it/eng/spagobi/commons/SimpleConfigurationRetriever.java index e7dc6bdad97..cc61d5e53cd 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/SimpleSingletonConfigCache.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/SimpleConfigurationRetriever.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -20,7 +20,7 @@ import java.util.HashMap; import java.util.Map; -public class SimpleSingletonConfigCache implements ISingletonConfigCache { +public class SimpleConfigurationRetriever implements IConfigurationRetriever { private final Map properties = new HashMap<>(); diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/SingletonConfig.java b/knowageutils/src/main/java/it/eng/spagobi/commons/SingletonConfig.java index 10034fd9062..676bd8190b4 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/SingletonConfig.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/SingletonConfig.java @@ -18,10 +18,10 @@ package it.eng.spagobi.commons; -import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; - import org.apache.log4j.Logger; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + /** * Defines the Singleton SpagoBI implementations. * @@ -30,54 +30,38 @@ public class SingletonConfig { - private static String CONFIG_CACHE_CLASS_NAME = "it.eng.spagobi.commons.SingletonConfigCache"; + private static final String CONFIG_RETRIEVER_CLASS_NAME = "it.eng.spagobi.commons.MetadataDatabaseConfigurationRetriever"; - private static SingletonConfig instance = null; - private static transient Logger logger = Logger.getLogger(SingletonConfig.class); + private static Logger logger = Logger.getLogger(SingletonConfig.class); - private ISingletonConfigCache cache; + private static final SingletonConfig instance = new SingletonConfig(); - public synchronized static SingletonConfig getInstance() { - try { - if (instance == null) - instance = new SingletonConfig(); - } catch (Exception e) { - logger.debug("Impossible to load configuration", e); - } + private IConfigurationRetriever retriever; + + public static SingletonConfig getInstance() { return instance; } - private SingletonConfig() throws Exception { + private SingletonConfig() { logger.debug("IN"); try { - cache = (ISingletonConfigCache) Class.forName(CONFIG_CACHE_CLASS_NAME).newInstance(); + retriever = (IConfigurationRetriever) Class.forName(CONFIG_RETRIEVER_CLASS_NAME).newInstance(); } catch (Exception e) { - throw new SpagoBIRuntimeException("Impossible to create " + CONFIG_CACHE_CLASS_NAME, e); + throw new SpagoBIRuntimeException("Impossible to instantiate " + CONFIG_RETRIEVER_CLASS_NAME, e); } + logger.debug("OUT"); } /** - * Gets the config. - * - * @return SourceBean contain the configuration + * Gets the configuration corresponding to the input key. * - * QUESTO METODO LO UTILIZZI PER LEGGERE LA CONFIGURAZIONE DEI SINGOLI ELEMENTI: ES: String configurazione= - * SingletonConfig.getInstance().getConfigValue("home.banner"); + * @return Returns the value of configuration by its key */ - public synchronized String getConfigValue(String key) { - return cache.get(key); - - } - - /** - * QUESTO METODO LO UTILIZZI ALL'INTERNO DEL SERVIZIO DI SALVATAGGIO CONFIGURAZIONE OGNI VOLTA CHE SALVIAMO UNA RIGA SVUOTIAMO LA CACHE - */ - public synchronized void clearCache() { - try { - instance = null; - } catch (Exception e) { - logger.debug("Impossible to create a new istance", e); - } + public String getConfigValue(String key) { + logger.debug("Retrieving configuration parameter with key [" + key + "]"); + String toReturn = retriever.get(key); + logger.debug("Retrieved configuration parameter with key [" + key + "]: [" + toReturn + "]"); + return toReturn; } /** @@ -85,17 +69,17 @@ public synchronized void clearCache() { * * @return */ - public ISingletonConfigCache getCache() { - return cache; + public IConfigurationRetriever getConfigurationRetriever() { + return retriever; } /** * for testing * - * @param cache + * @param retriever */ - public void setCache(ISingletonConfigCache cache) { - this.cache = cache; + public void setConfigurationRetriever(IConfigurationRetriever retriever) { + this.retriever = retriever; } } \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/bo/Role.java b/knowageutils/src/main/java/it/eng/spagobi/commons/bo/Role.java index a04185051b6..9b9e5323752 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/bo/Role.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/bo/Role.java @@ -42,6 +42,7 @@ public class Role implements Serializable { private Boolean isPublic; private boolean isAbleToEditPythonScripts; + private boolean isAbleToCreateCustomChart; private boolean isAbleToSaveSubobjects; private boolean isAbleToSeeSubobjects; private boolean isAbleToSeeViewpoints; @@ -105,6 +106,15 @@ public boolean isAbleToEditPythonScripts() { return isAbleToEditPythonScripts; } + /** + * Checks if is able to create custom chart. + * + * @return true, if is able to custom chart + */ + public boolean isAbleToCreateCustomChart() { + return isAbleToCreateCustomChart; + } + /** * Checks if is able to save subobjects. * @@ -117,7 +127,8 @@ public boolean isAbleToSaveSubobjects() { /** * Sets the checks if is able to save subobjects. * - * @param isAbleToSaveSubobjects the new checks if is able to save subobjects + * @param isAbleToSaveSubobjects + * the new checks if is able to save subobjects */ public void setIsAbleToSaveSubobjects(boolean isAbleToSaveSubobjects) { this.isAbleToSaveSubobjects = isAbleToSaveSubobjects; @@ -135,16 +146,28 @@ public boolean isAbleToSeeSubobjects() { /** * Sets the check if is able to edit python scripts. * - * @param isAbleToSeeSubobjects the new check if is able to edit python scripts + * @param isAbleToEditPythonScripts + * the new check if is able to edit python scripts */ public void setIsAbleToEditPythonScripts(boolean isAbleToEditPythonScripts) { this.isAbleToEditPythonScripts = isAbleToEditPythonScripts; } + /** + * Sets the check if is able to create custom chart. + * + * @param isAbleToCreateCustomChart + * the new check if is able to create custom chart + */ + public void setIsAbleToCreateCustomChart(boolean isAbleToCreateCustomChart) { + this.isAbleToCreateCustomChart = isAbleToCreateCustomChart; + } + /** * Sets the checks if is able to see subobjects. * - * @param isAbleToSeeSubobjects the new checks if is able to see subobjects + * @param isAbleToSeeSubobjects + * the new checks if is able to see subobjects */ public void setIsAbleToSeeSubobjects(boolean isAbleToSeeSubobjects) { this.isAbleToSeeSubobjects = isAbleToSeeSubobjects; @@ -162,7 +185,8 @@ public boolean isAbleToSeeViewpoints() { /** * Sets the checks if is able to see viewpoints. * - * @param isAbleToSeeViewpoints the new checks if is able to see viewpoints + * @param isAbleToSeeViewpoints + * the new checks if is able to see viewpoints */ public void setIsAbleToSeeViewpoints(boolean isAbleToSeeViewpoints) { this.isAbleToSeeViewpoints = isAbleToSeeViewpoints; @@ -180,7 +204,8 @@ public boolean isAbleToSeeSnapshots() { /** * Sets the checks if is able to see snapshots. * - * @param isAbleToSeeSnapshots the new checks if is able to see snapshots + * @param isAbleToSeeSnapshots + * the new checks if is able to see snapshots */ public void setIsAbleToSeeSnapshots(boolean isAbleToSeeSnapshots) { this.isAbleToSeeSnapshots = isAbleToSeeSnapshots; @@ -198,7 +223,8 @@ public boolean isAbleToRunSnapshots() { /** * Sets the checks if is able to run snapshots. * - * @param isAbleToRunSnapshots the new checks if is able to run snapshots + * @param isAbleToRunSnapshots + * the new checks if is able to run snapshots */ public void setIsAbleToRunSnapshots(boolean isAbleToRunSnapshots) { this.isAbleToRunSnapshots = isAbleToRunSnapshots; @@ -216,7 +242,8 @@ public boolean isAbleToSeeNotes() { /** * Sets the checks if is able to see notes. * - * @param isAbleToSeeNotes the new checks if is able to see notes + * @param isAbleToSeeNotes + * the new checks if is able to see notes */ public void setIsAbleToSeeNotes(boolean isAbleToSeeNotes) { this.isAbleToSeeNotes = isAbleToSeeNotes; @@ -234,7 +261,8 @@ public boolean isAbleToSendMail() { /** * Sets the checks if is able to send mail. * - * @param isAbleToSendMail the new checks if is able to send mail + * @param isAbleToSendMail + * the new checks if is able to send mail */ public void setIsAbleToSendMail(boolean isAbleToSendMail) { this.isAbleToSendMail = isAbleToSendMail; @@ -252,7 +280,8 @@ public boolean isAbleToSaveIntoPersonalFolder() { /** * Sets the checks if is able to save into personal folder. * - * @param isAbleToSaveIntoPersonalFolder the new checks if is able to save into personal folder + * @param isAbleToSaveIntoPersonalFolder + * the new checks if is able to save into personal folder */ public void setIsAbleToSaveIntoPersonalFolder(boolean isAbleToSaveIntoPersonalFolder) { this.isAbleToSaveIntoPersonalFolder = isAbleToSaveIntoPersonalFolder; @@ -270,7 +299,8 @@ public boolean isAbleToSaveRememberMe() { /** * Sets the checks if is able to save remember me. * - * @param isAbleToSaveRememberMe the new checks if is able to save remember me + * @param isAbleToSaveRememberMe + * the new checks if is able to save remember me */ public void setIsAbleToSaveRememberMe(boolean isAbleToSaveRememberMe) { this.isAbleToSaveRememberMe = isAbleToSaveRememberMe; @@ -288,7 +318,8 @@ public boolean isAbleToSeeMetadata() { /** * Sets the checks if is able to see metadata. * - * @param isAbleToSeeMetadata the new checks if is able to see metadata + * @param isAbleToSeeMetadata + * the new checks if is able to see metadata */ public void setIsAbleToSeeMetadata(boolean isAbleToSeeMetadata) { this.isAbleToSeeMetadata = isAbleToSeeMetadata; @@ -306,7 +337,8 @@ public boolean isAbleToSaveMetadata() { /** * Sets the checks if is able to save metadata. * - * @param isAbleToSaveMetadata the new checks if is able to save metadata + * @param isAbleToSaveMetadata + * the new checks if is able to save metadata */ public void setIsAbleToSaveMetadata(boolean isAbleToSaveMetadata) { this.isAbleToSaveMetadata = isAbleToSaveMetadata; @@ -341,8 +373,10 @@ public Role() { /** * Constructor. * - * @param name the name - * @param description the description + * @param name + * the name + * @param description + * the description */ public Role(String name, String description) { super(); @@ -363,7 +397,8 @@ public String getDescription() { /** * Sets the description. * - * @param description the description to set + * @param description + * the description to set */ public void setDescription(String description) { this.description = description; @@ -381,7 +416,8 @@ public Integer getId() { /** * Sets the id. * - * @param id the role id to set + * @param id + * the role id to set */ public void setId(Integer id) { this.id = id; @@ -399,7 +435,8 @@ public String getName() { /** * Sets the name. * - * @param name the name to set + * @param name + * the name to set */ public void setName(String name) { this.name = name; @@ -417,7 +454,8 @@ public String getRoleTypeCD() { /** * Sets the role type cd. * - * @param roleTypeCD The roleTypeCD to set. + * @param roleTypeCD + * The roleTypeCD to set. */ public void setRoleTypeCD(String roleTypeCD) { this.roleTypeCD = roleTypeCD; @@ -435,7 +473,8 @@ public Integer getRoleTypeID() { /** * Sets the role type id. * - * @param roleTypeID The roleTypeID to set. + * @param roleTypeID + * The roleTypeID to set. */ public void setRoleTypeID(Integer roleTypeID) { this.roleTypeID = roleTypeID; @@ -453,7 +492,8 @@ public String getCode() { /** * Sets the code. * - * @param code The code to set. + * @param code + * The code to set. */ public void setCode(String code) { this.code = code; @@ -491,7 +531,8 @@ public boolean isAbleToSeeDocumentBrowser() { } /** - * @param isAbleToSeeDocumentBrowser the isAbleToSeeDocumentBrowser to set + * @param isAbleToSeeDocumentBrowser + * the isAbleToSeeDocumentBrowser to set */ public void setIsAbleToSeeDocumentBrowser(boolean isAbleToSeeDocumentBrowser) { this.isAbleToSeeDocumentBrowser = isAbleToSeeDocumentBrowser; @@ -505,7 +546,8 @@ public boolean isAbleToSeeFavourites() { } /** - * @param isAbleToSeeFavourites the isAbleToSeeFavourites to set + * @param isAbleToSeeFavourites + * the isAbleToSeeFavourites to set */ public void setIsAbleToSeeFavourites(boolean isAbleToSeeFavourites) { this.isAbleToSeeFavourites = isAbleToSeeFavourites; @@ -519,7 +561,8 @@ public boolean isAbleToSeeSubscriptions() { } /** - * @param isAbleToSeeSubscriptions the isAbleToSeeSubscriptions to set + * @param isAbleToSeeSubscriptions + * the isAbleToSeeSubscriptions to set */ public void setIsAbleToSeeSubscriptions(boolean isAbleToSeeSubscriptions) { this.isAbleToSeeSubscriptions = isAbleToSeeSubscriptions; @@ -533,7 +576,8 @@ public boolean isAbleToSeeMyData() { } /** - * @param isAbleToSeeMyData the isAbleToSeeMyData to set + * @param isAbleToSeeMyData + * the isAbleToSeeMyData to set */ public void setIsAbleToSeeMyData(boolean isAbleToSeeMyData) { this.isAbleToSeeMyData = isAbleToSeeMyData; @@ -547,7 +591,8 @@ public boolean isAbleToSeeMyWorkspace() { } /** - * @param isAbleToSeeMyWorkspace the isAbleToSeeMyWorkspace to set + * @param isAbleToSeeMyWorkspace + * the isAbleToSeeMyWorkspace to set */ public void setIsAbleToSeeMyWorkspace(boolean isAbleToSeeMyWorkspace) { this.isAbleToSeeMyWorkspace = isAbleToSeeMyWorkspace; @@ -561,7 +606,8 @@ public boolean isAbleToSeeToDoList() { } /** - * @param isAbleToSeeToDoList the isAbleToSeeToDoList to set + * @param isAbleToSeeToDoList + * the isAbleToSeeToDoList to set */ public void setIsAbleToSeeToDoList(boolean isAbleToSeeToDoList) { this.isAbleToSeeToDoList = isAbleToSeeToDoList; @@ -575,7 +621,8 @@ public boolean isAbleToCreateDocuments() { } /** - * @param isAbleToCreateDocuments the isAbleToCreateDocuments to set + * @param isAbleToCreateDocuments + * the isAbleToCreateDocuments to set */ public void setIsAbleToCreateDocuments(boolean isAbleToCreateDocuments) { this.isAbleToCreateDocuments = isAbleToCreateDocuments; @@ -597,7 +644,8 @@ public List getRoleMetaModelCategories() { } /** - * @param roleMetaModelCategories the roleMetaModelCategories to set + * @param roleMetaModelCategories + * the roleMetaModelCategories to set */ public void setRoleMetaModelCategories(List roleMetaModelCategories) { this.roleMetaModelCategories = roleMetaModelCategories; diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/bo/RoleBO.java b/knowageutils/src/main/java/it/eng/spagobi/commons/bo/RoleBO.java index 2f059fd7230..888294a2c04 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/bo/RoleBO.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/bo/RoleBO.java @@ -70,6 +70,7 @@ public class RoleBO implements Serializable { private Boolean isPublic; private boolean ableToEditPythonScripts; + private boolean ableToCreateCustomChart; private boolean ableToSaveSubobjects; private boolean ableToSeeSubobjects; private boolean ableToSeeViewpoints; @@ -134,8 +135,10 @@ public RoleBO() { /** * Constructor. * - * @param name the name - * @param description the description + * @param name + * the name + * @param description + * the description */ public RoleBO(String name, String description) { super(); @@ -156,7 +159,8 @@ public String getDescription() { /** * Sets the description. * - * @param description the description to set + * @param description + * the description to set */ public void setDescription(String description) { this.description = description; @@ -174,7 +178,8 @@ public Integer getId() { /** * Sets the id. * - * @param id the role id to set + * @param id + * the role id to set */ public void setId(Integer id) { this.id = id; @@ -192,7 +197,8 @@ public String getName() { /** * Sets the name. * - * @param name the name to set + * @param name + * the name to set */ public void setName(String name) { this.name = name; @@ -210,7 +216,8 @@ public String getRoleTypeCD() { /** * Sets the role type cd. * - * @param roleTypeCD The roleTypeCD to set. + * @param roleTypeCD + * The roleTypeCD to set. */ public void setRoleTypeCD(String roleTypeCD) { this.roleTypeCD = roleTypeCD; @@ -228,7 +235,8 @@ public Integer getRoleTypeID() { /** * Sets the role type id. * - * @param roleTypeID The roleTypeID to set. + * @param roleTypeID + * The roleTypeID to set. */ public void setRoleTypeID(Integer roleTypeID) { this.roleTypeID = roleTypeID; @@ -246,7 +254,8 @@ public String getCode() { /** * Sets the code. * - * @param code The code to set. + * @param code + * The code to set. */ public void setCode(String code) { this.code = code; @@ -272,10 +281,18 @@ public boolean isAbleToEditPythonScripts() { return ableToEditPythonScripts; } + public boolean isAbleToCreateCustomChart() { + return ableToCreateCustomChart; + } + public void setAbleToEditPythonScripts(boolean ableToEditPythonScripts) { this.ableToEditPythonScripts = ableToEditPythonScripts; } + public void setAbleToCreateCustomChart(boolean ableToCreateCustomChart) { + this.ableToCreateCustomChart = ableToCreateCustomChart; + } + public boolean isAbleToSaveSubobjects() { return ableToSaveSubobjects; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/commons/constants/SpagoBIConstants.java b/knowageutils/src/main/java/it/eng/spagobi/commons/constants/SpagoBIConstants.java index a59695587e0..5ff5577504d 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/commons/constants/SpagoBIConstants.java +++ b/knowageutils/src/main/java/it/eng/spagobi/commons/constants/SpagoBIConstants.java @@ -401,6 +401,7 @@ public class SpagoBIConstants { public static final String READ_ROLES = "ReadRoles"; public static final String EDIT_PYTHON_SCRIPTS = "EditPythonScripts"; + public static final String CREATE_CUSTOM_CHART = "CreateCustomChart"; public static final String SAVE_SUBOBJECT_FUNCTIONALITY = "SaveSubobjectFunctionality"; public static final String SEE_SUBOBJECTS_FUNCTIONALITY = "SeeSubobjectsFunctionality"; public static final String SEE_VIEWPOINTS_FUNCTIONALITY = "SeeViewpointsFunctionality"; diff --git a/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProvider.java b/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProvider.java new file mode 100644 index 00000000000..0a389245731 --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProvider.java @@ -0,0 +1,106 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.security; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; + +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.apache.log4j.Logger; + +import it.eng.knowage.wapp.Version; +import sun.misc.BASE64Encoder; + +/** + * @author Franco vuoto (franco.vuoto@eng.it) + * @author Alessandro Pegoraro (alessandro.pegoraro@eng.it) + * + */ +public enum AsymmetricProvider { + INSTANCE(getKeyBytes()), OLD_INSTANCE(getOldKeyBytes()); + + private String PROVIDER = "HmacSHA1"; + private Mac mac = null; + + private AsymmetricProvider(byte[] keyBytes) { + Provider sunJce = new com.sun.crypto.provider.SunJCE(); + Security.addProvider(sunJce); + + SecretKey key = new SecretKeySpec(keyBytes, PROVIDER); + + try { + mac = Mac.getInstance(PROVIDER); + mac.init(key); + } catch (NoSuchAlgorithmException e) { + throw new Error("Unable to find algorithm for security initialization", e); + } catch (InvalidKeyException e) { + throw new Error("Unable to find a valid key for security initialization", e); + } + } + + public String enCrypt(String value) { + byte[] result = mac.doFinal(value.getBytes()); + + BASE64Encoder encoder = new BASE64Encoder(); + String encoded = encoder.encode(result); + + return encoded; + } + + private static byte[] getKeyBytes() { + String documentationLink = String.format( + "Please, read the documentation https://knowage-suite.readthedocs.io/en/%s.%s/installation-guide/manual-installation.html?highlight=server.xml#environment-variables-definition", + Version.getMajorVersion(), Version.getMinorVersion()); + Logger logger = Logger.getLogger(AsymmetricProvider.class); + byte[] fileContent = null; + try { + String fileLocation = (String) new InitialContext().lookup("java:/comp/env/password_encryption_secret"); + + File file = new File(fileLocation); + fileContent = Files.readAllBytes(file.toPath()); + + } catch (NamingException e) { + String message = "Unable to find resource for security initialization. [password_encryption_secret] envinronment variable is missing."; + logger.error(String.format("%s %s", message, documentationLink)); + throw new Error(message, e); + } catch (IOException e) { + String message = "Unable to find file for security initialization."; + logger.error(String.format("%s %s", message, documentationLink)); + throw new Error(message, e); + } + + return fileContent; + } + + private static byte[] getOldKeyBytes() { + byte[] keyBytes = { (byte) 0x06, (byte) 0xAB, (byte) 0x12, (byte) 0xE4, (byte) 0xE4, (byte) 0xE4, (byte) 0xE4, (byte) 0x12, (byte) 0x13, (byte) 0xE4, + (byte) 0x12, (byte) 0xCC, (byte) 0xEF, (byte) 0xE4, (byte) 0x06, (byte) 0x07, (byte) 0xE4, (byte) 0x07, (byte) 0x12, (byte) 0xCD, (byte) 0xE4, + (byte) 0x07, (byte) 0xFE, (byte) 0xFF, (byte) 0x07, (byte) 0xE4, (byte) 0x08 }; + return keyBytes; + } +} \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProviderSingleton.java b/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProviderSingleton.java deleted file mode 100644 index 52af150d79b..00000000000 --- a/knowageutils/src/main/java/it/eng/spagobi/security/AsymmetricProviderSingleton.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -package it.eng.spagobi.security; - - -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.Security; - -import javax.crypto.Mac; -import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; - - -import sun.misc.BASE64Encoder; - -/** - * @author Franco vuoto (franco.vuoto@eng.it) - * @author Alessandro Pegoraro (alessandro.pegoraro@eng.it) - * - */ -public class AsymmetricProviderSingleton { - private static final String PROVIDER = "HmacSHA1"; - - - private static AsymmetricProviderSingleton _instance = null; - private Mac mac = null; - - public static AsymmetricProviderSingleton getInstance() throws InvalidKeyException, NoSuchAlgorithmException { - if (_instance == null) { - synchronized (AsymmetricProviderSingleton.class) { - if (_instance == null) - _instance = new AsymmetricProviderSingleton(); - } - } - return _instance; - } - - private AsymmetricProviderSingleton() throws InvalidKeyException,NoSuchAlgorithmException { - Provider sunJce = new com.sun.crypto.provider.SunJCE(); - Security.addProvider(sunJce); - - SecretKey key = new SecretKeySpec(keyBytes, PROVIDER); - - mac = Mac.getInstance(PROVIDER); - mac.init(key); - - } - - public String enCrypt(String value) { - byte[] result = mac.doFinal(value.getBytes()); - - BASE64Encoder encoder = new BASE64Encoder(); - String encoded = encoder.encode(result); - - return encoded; - } - - private static byte[] keyBytes = - { - (byte) 0x06, - (byte) 0xAB, - (byte) 0x12, - (byte) 0xE4, - (byte) 0xE4, - (byte) 0xE4, - (byte) 0xE4, - (byte) 0x12, - (byte) 0x13, - (byte) 0xE4, - (byte) 0x12, - (byte) 0xCC, - (byte) 0xEF, - (byte) 0xE4, - (byte) 0x06, - (byte) 0x07, - (byte) 0xE4, - (byte) 0x07, - (byte) 0x12, - (byte) 0xCD, - (byte) 0xE4, - (byte) 0x07, - (byte) 0xFE, - (byte) 0xFF, - (byte) 0x07, - (byte) 0xE4, - (byte) 0x08 }; - - -} \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/spagobi/security/Password.java b/knowageutils/src/main/java/it/eng/spagobi/security/Password.java index 7c66cbabf13..90a0f6b4a8a 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/security/Password.java +++ b/knowageutils/src/main/java/it/eng/spagobi/security/Password.java @@ -17,6 +17,7 @@ */ package it.eng.spagobi.security; +import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -31,6 +32,8 @@ */ public class Password { + private static final String PREFIX_V2_SHA_PWD_ENCRIPTING = "v2#SHA#"; + public static final String PREFIX_SHA_PWD_ENCRIPTING = "#SHA#"; private String value = ""; private String encValue = ""; @@ -57,10 +60,11 @@ private void validate() { for (int i = 0; i < value.length(); i++) { int c = value.charAt(i); - if ((c >= 'A') && (c <= 'Z') ) { + if ((c >= 'A') && (c <= 'Z')) { contaAlfaUpperCase++; - }if ( (c >= 'a') && (c <= 'z')) { - contaAlfaLowerCase++; + } + if ((c >= 'a') && (c <= 'z')) { + contaAlfaLowerCase++; } else if ((c >= '0') && (c <= '9')) { contaNum++; } else { @@ -77,28 +81,32 @@ public Password(String value) { } public boolean hasAltenateCase() { - return ( (contaAlfaUpperCase>=1 ) && (contaAlfaLowerCase>=1) ); - } + return ((contaAlfaUpperCase >= 1) && (contaAlfaLowerCase >= 1)); + } public boolean hasDigits() { - return (contaNum>0); + return (contaNum > 0); } public boolean isEnoughLong() { - return (value.length() >=8); + return (value.length() >= 8); } /** * @return * @throws NoSuchAlgorithmException * @throws InvalidKeyException + * @throws IOException */ - public String getEncValue() throws InvalidKeyException, NoSuchAlgorithmException{ + public String getEncValue(boolean before72) throws InvalidKeyException, NoSuchAlgorithmException, IOException { if (encValue != null) { - AsymmetricProviderSingleton bs = AsymmetricProviderSingleton.getInstance(); - encValue = "#SHA#" + bs.enCrypt(value); + if (before72) { + encValue = PREFIX_SHA_PWD_ENCRIPTING + AsymmetricProvider.OLD_INSTANCE.enCrypt(value); + } else { + encValue = PREFIX_V2_SHA_PWD_ENCRIPTING + AsymmetricProvider.INSTANCE.enCrypt(value); + } } return encValue; } @@ -110,7 +118,6 @@ public String getValue() { return value; } - /** * @param string */ @@ -118,6 +125,7 @@ public void setValue(String string) { value = string; validate(); } + /** * public method used to store passwords on DB. * @@ -125,22 +133,26 @@ public void setValue(String string) { * @return encrypted password * @throws Exception wrapping InvalidKeyException and NoSuchAlgorithmException */ - public static String encriptPassword(String password) throws Exception { - if (password != null){ - String enable=SingletonConfig.getInstance().getConfigValue("internal.security.encript.password"); - if ("true".equalsIgnoreCase(enable)){ + public static String encriptPassword(String password, boolean before72) throws Exception { + if (password != null) { + String enable = SingletonConfig.getInstance().getConfigValue("internal.security.encript.password"); + if ("true".equalsIgnoreCase(enable)) { Password hashPass = new Password(password); try { - password = (hashPass.getEncValue()); + password = (hashPass.getEncValue(before72)); } catch (InvalidKeyException e) { - logger.error("HASH not valid", e); - throw new Exception("HASH not valid",e); + logger.error("not valid HASH", e); + throw new Exception("not valid HASH", e); } catch (NoSuchAlgorithmException e) { - logger.error("Impossibile to calcolate l'HASH", e); - throw new Exception("Impossibile to calcolate l'HASH",e); + logger.error("Impossible to calcolate HASH", e); + throw new Exception("Impossible to calcolate HASH", e); } } } return password; } + + public static String encriptPassword(String password) throws Exception { + return encriptPassword(password, false); + } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractDataSet.java index 16cb256854f..762aa58ddc6 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractDataSet.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractDataSet.java @@ -422,8 +422,7 @@ private String[] getValuesAsArray(Map paramValues, String paramN /** * Encapsulate values into SQL values. * - * For every type of data except string, the method convert the values - * to strings. + * For every type of data except string, the method convert the values to strings. * * With strings we can have two case: *
    @@ -431,15 +430,13 @@ private String[] getValuesAsArray(Map paramValues, String paramN *
  • String that doesn't start and end with single quote
  • *
* - * In the first case, FE are sending us SQL values that probably contain - * JSON escape (e.g., a JSON value like 'this string contains a \' in it'). + * In the first case, FE are sending us SQL values that probably contain JSON escape (e.g., a JSON value like 'this string contains a \' in it'). * - * In the second case, FE are sending us standard not-SQL-escaded string ( - * e.g., a string like "this string contains a ' in it"). In this second case - * this method escapes single quote and duplicates them as requested by SQL. + * In the second case, FE are sending us standard not-SQL-escaded string ( e.g., a string like "this string contains a ' in it"). In this second case this + * method escapes single quote and duplicates them as requested by SQL. * * @param parameter Original parameter JSON metadata - * @param values Actual values of parameters + * @param values Actual values of parameters * @return List of encapsulated values as strings */ private List encapsulateValues(JSONObject parameter, String[] values) { @@ -452,7 +449,30 @@ private List encapsulateValues(JSONObject parameter, String[] values) { String value = values[j].trim(); if (!value.isEmpty()) { if (value.startsWith(delim) && value.endsWith(delim)) { - newValues.add(value); + if (value.contains("','")) { + String[] valuesArray = value.split("','"); + String newValuesFromArray = ""; + for (int i = 0; i < valuesArray.length; i++) { + String temp = valuesArray[i]; + if (i == 0) + temp = temp + delim; + else + temp = delim + temp; + if (temp.startsWith(delim) && temp.endsWith(delim)) + temp = temp.substring(1, temp.length() - 1); + temp = temp.replaceAll("'", "''"); + if (i == 0) + newValuesFromArray = (delim + temp + delim); + else + newValuesFromArray = newValuesFromArray + "," + (delim + temp + delim); + + } + newValues.add(newValuesFromArray); + } else { + value = value.substring(1, value.length() - 1); + value = value.replaceAll("'", "''"); + newValues.add(delim + value + delim); + } } else { if (isString) { // Duplicate single quote to transform it into an escaped SQL single quote diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractJDBCDataset.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractJDBCDataset.java index 86a7094de5d..81c4f71e478 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractJDBCDataset.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/AbstractJDBCDataset.java @@ -35,6 +35,7 @@ import it.eng.spagobi.tools.dataset.common.behaviour.QuerableBehaviour; import it.eng.spagobi.tools.dataset.common.dataproxy.IDataProxy; import it.eng.spagobi.tools.dataset.common.dataproxy.JDBCDataProxy; +import it.eng.spagobi.tools.dataset.common.dataproxy.JDBCRedShiftDataProxy; import it.eng.spagobi.tools.dataset.common.datareader.AbstractDataReader; import it.eng.spagobi.tools.dataset.common.datareader.JDBCStandardDataReader; import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; @@ -164,7 +165,7 @@ public JDBCDataProxy getDataProxy() { dataProxy = getDataProxy(); } - if (!(dataProxy instanceof JDBCDataProxy)) + if (!(dataProxy instanceof JDBCDataProxy) && !(dataProxy instanceof JDBCRedShiftDataProxy)) throw new RuntimeException("DataProxy cannot be of type [" + dataProxy.getClass().getName() + "] in JDBCDataSet"); return (JDBCDataProxy) dataProxy; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/CkanDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/CkanDataSet.java index 4dcf4a78a6a..610afaa6953 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/CkanDataSet.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/CkanDataSet.java @@ -17,8 +17,6 @@ */ package it.eng.spagobi.tools.dataset.bo; -import java.util.Map; - import org.apache.log4j.Logger; import org.json.JSONObject; @@ -248,23 +246,4 @@ public IDataSource getDataSource() { return null; } - /* - * (non-Javadoc) - * - * @see it.eng.spagobi.tools.dataset.bo.IDataSet#getDrivers() - */ - @Override - public Map getDrivers() { - return getDrivers(); - } - - /* - * (non-Javadoc) - * - * @see it.eng.spagobi.tools.dataset.bo.IDataSet#setDrivers(java.util.HashMap) - */ - @Override - public void setDrivers(Map drivers) { - setDrivers(drivers); - } } \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/DataSetFactory.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/DataSetFactory.java index 04cf9eed7aa..9b648330801 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/DataSetFactory.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/DataSetFactory.java @@ -53,12 +53,9 @@ public static IDataSet getDataSet(SpagoBiDataSet dataSetConfig, String userId) { /** * This method returns a dataset according to his configuration * - * @param dataSetConfig - * dataset configuration - * @param userId - * used in QBE dataset - * @param session - * sd in QBE dataset + * @param dataSetConfig dataset configuration + * @param userId used in QBE dataset + * @param session sd in QBE dataset * @return a dataset correctly configured */ public static IDataSet getDataSet(SpagoBiDataSet dataSetConfig, String userId, HttpSession session) { @@ -108,6 +105,8 @@ public static IDataSet getDataSet(SpagoBiDataSet dataSetConfig, String userId, H className = JDBCOrientDbDataSet.class.getName(); } else if (dialectToLowerCase.contains("vertica")) { className = JDBCVerticaDataSet.class.getName(); + } else if (dialectToLowerCase.contains("RedShift")) { + className = JDBCRedShiftDataSet.class.getName(); } } try { diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/FlatDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/FlatDataSet.java index eb389d1294b..a1fc93245b6 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/FlatDataSet.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/FlatDataSet.java @@ -18,6 +18,10 @@ package it.eng.spagobi.tools.dataset.bo; +import org.apache.log4j.Logger; +import org.json.JSONException; +import org.json.JSONObject; + import it.eng.spagobi.container.ObjectUtils; import it.eng.spagobi.services.dataset.bo.SpagoBiDataSet; import it.eng.spagobi.tools.datasource.bo.DataSourceFactory; @@ -25,9 +29,6 @@ import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; import it.eng.spagobi.utilities.json.JSONUtils; -import org.apache.log4j.Logger; -import org.json.JSONObject; - /** * @authors Davide Zerbetto (davide.zerbetto@eng.it) * @@ -37,7 +38,8 @@ public class FlatDataSet extends ConfigurableDataSet { public static String DS_TYPE = "SbiFlatDataSet"; public static final String FLAT_TABLE_NAME = "flatTableName"; - public static final String DATA_SOURCE = "dataSource"; + public static final String DATA_SOURCE = "dataSourceFlat"; + public static final String OLD_DATA_SOURCE = "dataSource"; private static transient Logger logger = Logger.getLogger(FlatDataSet.class); @@ -111,6 +113,27 @@ public SpagoBiDataSet toSpagoBiDataSet() { return toReturn; } + @Override + public void setConfiguration(String configuration) { + /* WORKAROUND : in the past the datasource attribute was + * dataSource and not dataSourceFlat. + */ + String config = JSONUtils.escapeJsonString(configuration); + JSONObject jsonConf = ObjectUtils.toJSONObject(config); + if (jsonConf.has(OLD_DATA_SOURCE)) { + try { + String string = jsonConf.getString(OLD_DATA_SOURCE); + jsonConf.put(DATA_SOURCE, string); + jsonConf.remove(OLD_DATA_SOURCE); + configuration = jsonConf.toString(); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } + + super.setConfiguration(configuration); + } + @Override public String getDsType() { return DS_TYPE; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCDatasetFactory.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCDatasetFactory.java index 5904e98efb3..4d3c5e78ddd 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCDatasetFactory.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCDatasetFactory.java @@ -57,6 +57,9 @@ public static IDataSet getJDBCDataSet(IDataSource dataSource) { case VERTICA: dataSet = new JDBCVerticaDataSet(); break; + case REDSHIFT: + dataSet = new JDBCRedShiftDataSet(); + break; default: dataSet = new JDBCDataSet(); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCRedShiftDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCRedShiftDataSet.java new file mode 100644 index 00000000000..edd2ecac61a --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/JDBCRedShiftDataSet.java @@ -0,0 +1,53 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.spagobi.tools.dataset.bo; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.services.dataset.bo.SpagoBiDataSet; +import it.eng.spagobi.tools.dataset.common.dataproxy.JDBCRedShiftDataProxy; +import it.eng.spagobi.tools.dataset.common.datareader.AbstractDataReader; +import it.eng.spagobi.tools.dataset.common.datareader.JDBCStandardDataReader; + +/** + * @author Matteo Massarotto + */ +public class JDBCRedShiftDataSet extends AbstractJDBCDataset { + + private static transient Logger logger = Logger.getLogger(JDBCRedShiftDataSet.class); + + /** + * Instantiates a new empty JDBC RedShift data set. + */ + public JDBCRedShiftDataSet() { + super(); + setDataProxy(new JDBCRedShiftDataProxy()); + setDataReader(createDataReader()); + } + + public JDBCRedShiftDataSet(SpagoBiDataSet dataSetConfig) { + super(dataSetConfig); + } + + @Override + protected AbstractDataReader createDataReader() { + return new JDBCStandardDataReader(); + } + +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/PythonDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/PythonDataSet.java index f993d1ae50d..448b039806e 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/PythonDataSet.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/PythonDataSet.java @@ -119,25 +119,28 @@ private void initDataReader(JSONObject jsonConf) { private void initDataProxy(JSONObject jsonConf) { String restAddress; Map requestHeaders; + String pythonDatasetType = getProp(PythonDataSetConstants.PYTHON_DATASET_TYPE, jsonConf, true); try { requestHeaders = getRequestHeadersPropMap(PythonDataSetConstants.REST_REQUEST_HEADERS, jsonConf); JSONObject pythonEnv = new JSONObject(getProp(PythonDataSetConstants.PYTHON_ENVIRONMENT, jsonConf, false)); String label = pythonEnv.get("label").toString(); String pythonAddress = SingletonConfig.getInstance().getConfigValue(label); - restAddress = "https://" + pythonAddress + "/dataset"; + if (pythonDatasetType != null && pythonDatasetType.equals("r")) + restAddress = "http://" + pythonAddress + "/dataset"; // R engine does not support https + else + restAddress = "https://" + pythonAddress + "/dataset"; +// restAddress = "https://" + pythonAddress + "/dataset"; } catch (Exception e) { throw new ConfigurationException("Problems in configuration of data proxy", e); } String pythonScript = getProp(PythonDataSetConstants.PYTHON_SCRIPT, jsonConf, true); + String parameters = getProp(PythonDataSetConstants.PYTHON_SCRIPT_PARAMETERS, jsonConf, true); String dataframeName = getProp(PythonDataSetConstants.PYTHON_DATAFRAME_NAME, jsonConf, true); - // Pagination parameters String offset = getProp(PythonDataSetConstants.REST_OFFSET, jsonConf, true); String fetchSize = getProp(PythonDataSetConstants.REST_FETCH_SIZE, jsonConf, true); String maxResults = getProp(PythonDataSetConstants.REST_MAX_RESULTS, jsonConf, true); - String parameters = getProp(PythonDataSetConstants.PYTHON_SCRIPT_PARAMETERS, jsonConf, true); - setDataProxy(new PythonDataProxy(restAddress, pythonScript, dataframeName, parameters, requestHeaders, offset, fetchSize, maxResults)); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/SolrDataSet.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/SolrDataSet.java index 2ba01e6681f..623e64d64c7 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/SolrDataSet.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/bo/SolrDataSet.java @@ -258,7 +258,7 @@ public JSONArray getSolrFields(boolean force) { } if (force || solrFields.length() == 0) { - RestUtilities.Response response = RestUtilities.makeRequest(dataProxy.getRequestMethod(), + RestUtilities.Response response = RestUtilities.makeRequest(HttpMethod.Get, solrConfiguration.getUrl() + solrConfiguration.getCollection() + "/schema/fields?wt=json", dataProxy.getRequestHeaders(), null, null); logger.debug(response.getStatusCode()); Assert.assertTrue(response.getStatusCode() == HttpStatus.SC_OK, "Response status is not ok"); @@ -285,7 +285,22 @@ private void initDataProxy(JSONObject jsonConf, boolean resolveParams) { String maxResults = getProp(RESTDataSetConstants.REST_MAX_RESULTS, jsonConf, true, resolveParams); String facetField = getSolrFacetField(jsonConf, resolveParams); - setDataProxy(new SolrDataProxy(solrConfiguration.toString(), HttpMethod.Get, facetField, requestHeaders, offset, fetchSize, maxResults, isFacet())); + + String body = null; + String address = null; + /* + * In case in the future we will let the user to choose + * between GET and POST... + */ + HttpMethod method = HttpMethod.Post; + if (method == HttpMethod.Get) { + address = solrConfiguration.toString(); + } else if (method == HttpMethod.Post) { + address = solrConfiguration.toString(false); + body = solrConfiguration.getQueryParameters(); + requestHeaders.put("Content-Type", "application/x-www-form-urlencoded"); + } + setDataProxy(new SolrDataProxy(address, method, body, facetField, requestHeaders, offset, fetchSize, maxResults, isFacet())); } protected String getSolrFacetField(JSONObject jsonConf, boolean resolveParams) { diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCDataProxy.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCDataProxy.java index 34edc42ef41..fa4443b2ee7 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCDataProxy.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCDataProxy.java @@ -22,8 +22,12 @@ import java.sql.SQLException; import java.sql.Statement; +import org.apache.log4j.LogMF; import org.apache.log4j.Logger; +import com.jamonapi.Monitor; +import com.jamonapi.MonitorFactory; + import it.eng.spago.error.EMFUserError; import it.eng.spagobi.tools.dataset.common.datareader.IDataReader; import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; @@ -91,11 +95,17 @@ public IDataStore load(IDataReader dataReader) { try { + Monitor timeToGetConnection = MonitorFactory.start("Knowage.JDBCDataProxy.gettingJDBCConnection"); + logger.debug("Retrieving JDBC connection..."); try { connection = getDataSource().getConnection(); } catch (Exception t) { throw new SpagoBIRuntimeException("An error occurred while creating connection", t); + } finally { + timeToGetConnection.stop(); } + logger.debug("Got JDBC connection."); + String dialect = dataSource.getHibDialectClass(); DatabaseDialect databaseDialect = DatabaseDialect.get(dialect); Assert.assertNotNull(dialect, "Database dialect cannot be null"); @@ -106,7 +116,7 @@ public IDataStore load(IDataReader dataReader) { if (databaseDialect.equals(DatabaseDialect.HIVE) || databaseDialect.equals(DatabaseDialect.HIVE2) || databaseDialect.equals(DatabaseDialect.CASSANDRA) || databaseDialect.equals(DatabaseDialect.IMPALA) || databaseDialect.equals(DatabaseDialect.ORIENT) || databaseDialect.equals(DatabaseDialect.SPARKSQL) - || databaseDialect.equals(DatabaseDialect.VERTICA)) { + || databaseDialect.equals(DatabaseDialect.VERTICA) || databaseDialect.equals(DatabaseDialect.REDSHIFT)) { stmt = connection.createStatement(); } else { stmt = connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); @@ -114,6 +124,7 @@ public IDataStore load(IDataReader dataReader) { } catch (Exception t) { throw new SpagoBIRuntimeException("An error occurred while creating connection steatment", t); } + String sqlQuery = ""; try { // get max size @@ -121,9 +132,14 @@ public IDataStore load(IDataReader dataReader) { stmt.setMaxRows(getMaxResults()); } sqlQuery = getStatement(); - logger.info("Executing query " + sqlQuery + " ..."); - resultSet = stmt.executeQuery(sqlQuery); - + LogMF.info(logger, "Executing query:\n{0}", sqlQuery); + Monitor timeToExecuteStatement = MonitorFactory.start("Knowage.JDBCDataProxy.executeStatement:" + sqlQuery); + try { + resultSet = stmt.executeQuery(sqlQuery); + } finally { + timeToExecuteStatement.stop(); + } + LogMF.debug(logger, "Query has been executed:\n{0}", sqlQuery); } catch (Exception t) { throw new SpagoBIRuntimeException("An error occurred while executing statement: " + sqlQuery, t); } @@ -165,12 +181,17 @@ public IDataStore load(IDataReader dataReader) { } dataStore = null; + Monitor timeToGetDataStore = MonitorFactory.start("Knowage.JDBCDataProxy.getDataStore:" + sqlQuery); + LogMF.debug(logger, "Getting datastore for SQL query:\n{0}", sqlQuery); try { // read data dataStore = dataReader.read(resultSet); } catch (Exception t) { throw new SpagoBIRuntimeException("An error occurred while parsing resultset", t); + } finally { + timeToGetDataStore.stop(); } + LogMF.debug(logger, "Got datastore for SQL query:\n{0}", sqlQuery); if (resultNumber > -1) { // it means that resultNumber was successfully calculated by this data proxy int limitedResultNumber = getMaxResults() > 0 && resultNumber > getMaxResults() ? getMaxResults() : resultNumber; @@ -205,22 +226,28 @@ protected int getResultNumber(Connection connection) { logger.debug("we are in SQL SERVER and ORDER BY case"); statement = modifySQLServerQuery(statement); } - try { String tableAlias = ""; if (!dialect.toLowerCase().contains("orient")) { tableAlias = "temptable"; } String sqlQuery = "SELECT COUNT(*) FROM (" + statement + ") " + tableAlias; - logger.info("Executing query " + sqlQuery + " ..."); stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); - rs = stmt.executeQuery(sqlQuery); + LogMF.info(logger, "Executing count statement, SQL query:\n{0}", sqlQuery); + Monitor timeToExecuteStatement = MonitorFactory.start("Knowage.JDBCDataProxy.executeCountStatement:" + sqlQuery); + try { + rs = stmt.executeQuery(sqlQuery); + } finally { + timeToExecuteStatement.stop(); + } + LogMF.debug(logger, "Executed count statement, SQL query:\n{0}", sqlQuery); rs.next(); resultNumber = rs.getInt(1); } catch (Throwable t) { throw new SpagoBIRuntimeException("An error occurred while creating connection steatment", t); } finally { releaseResources(null, stmt, rs); + } logger.debug("OUT : returning " + resultNumber); return resultNumber; @@ -260,7 +287,7 @@ private String modifySQLServerQuery(String statement) { protected int getResultNumber(ResultSet resultSet) throws SQLException { logger.debug("IN"); - + LogMF.debug(logger, "Moving into last record for statement:\n{0}", resultSet.getStatement().toString()); int rowcount = 0; if (resultSet.last()) { rowcount = resultSet.getRow(); @@ -268,7 +295,7 @@ protected int getResultNumber(ResultSet resultSet) throws SQLException { // below will move on, missing the first // element } - + LogMF.debug(logger, "Moved into last record for statement:\n{0}", resultSet.getStatement().toString()); return rowcount; } @@ -332,8 +359,14 @@ public ResultSet getData(IDataReader dataReader, Object... resources) { stmt.setMaxRows(getMaxResults()); } String sqlQuery = getStatement(); - logger.info("Executing query " + sqlQuery + " ..."); - resultSet = stmt.executeQuery(sqlQuery); + LogMF.info(logger, "Executing query:\n{0}", sqlQuery); + Monitor timeToExecuteStatement = MonitorFactory.start("Knowage.JDBCDataProxy.executeStatement:" + sqlQuery); + try { + resultSet = stmt.executeQuery(sqlQuery); + } finally { + timeToExecuteStatement.stop(); + } + LogMF.debug(logger, "Executed query:\n{0}", sqlQuery); return resultSet; } catch (SQLException e) { throw new SpagoBIRuntimeException(e); diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCRedShiftDataProxy.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCRedShiftDataProxy.java new file mode 100644 index 00000000000..febbbd525a0 --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/JDBCRedShiftDataProxy.java @@ -0,0 +1,399 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package it.eng.spagobi.tools.dataset.common.dataproxy; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import org.apache.log4j.Logger; + +import it.eng.spago.error.EMFUserError; +import it.eng.spagobi.tools.dataset.common.datareader.IDataReader; +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; +import it.eng.spagobi.tools.datasource.bo.IDataSource; +import it.eng.spagobi.utilities.assertion.Assert; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; + +/** + * @author Andrea Gioia (andrea.gioia@eng.it) + */ +public class JDBCRedShiftDataProxy extends JDBCDataProxy { + + IDataSource dataSource; + String statement; + String schema; + int fetchSize; + int offset; + + private static transient Logger logger = Logger.getLogger(JDBCRedShiftDataProxy.class); + + public JDBCRedShiftDataProxy(int offsetParam, int fetchSizeParam) { + this.setCalculateResultNumberOnLoad(true); + this.offset = offsetParam; + this.fetchSize = fetchSizeParam; + } + + public JDBCRedShiftDataProxy() { + this.setCalculateResultNumberOnLoad(true); + } + + public JDBCRedShiftDataProxy(IDataSource dataSource, String statement, int offsetParam, int fetchSizeParam) { + this(offsetParam, fetchSizeParam); + setDataSource(dataSource); + setStatement(statement); + } + + public JDBCRedShiftDataProxy(IDataSource dataSource, int offsetParam, int fetchSizeParam) { + this(offsetParam, fetchSizeParam); + setDataSource(dataSource); + setStatement(statement); + } + + public JDBCRedShiftDataProxy(IDataSource dataSource) { + setDataSource(dataSource); + } + + @Override + public String getSchema() { + return schema; + } + + @Override + public void setSchema(String schema) { + this.schema = schema; + } + + @Override + public IDataStore load(String statement, IDataReader dataReader) throws EMFUserError { + if (statement != null) { + setStatement(statement); + } + return load(dataReader); + } + + @Override + public IDataStore load(IDataReader dataReader) { + + IDataStore dataStore; + Connection connection; + Statement stmt; + ResultSet resultSet; + + logger.debug("IN"); + + connection = null; + stmt = null; + resultSet = null; + + try { + + try { + connection = getDataSource().getConnection(); + } catch (Exception t) { + throw new SpagoBIRuntimeException("An error occurred while creating connection", t); + } + String dialect = dataSource.getHibDialectClass(); + Assert.assertNotNull(dialect, "Database dialect cannot be null"); + try { + + stmt = connection.createStatement(); + + } catch (Exception t) { + throw new SpagoBIRuntimeException("An error occurred while creating connection steatment", t); + } + String sqlQuery = ""; + try { + // get max size + if (getMaxResults() > 0) { + stmt.setMaxRows(getMaxResults()); + } + sqlQuery = getStatement(); + logger.info("Executing query " + sqlQuery + " ..."); + resultSet = stmt.executeQuery(sqlQuery); + + } catch (Exception t) { + throw new SpagoBIRuntimeException("An error occurred while executing statement: " + sqlQuery, t); + } + + int resultNumber = -1; + if (isCalculateResultNumberOnLoadEnabled()) { + logger.debug("Calculation of result set total number is enabled"); + try { + + // try to calculate the query total result number using inline view tecnique + resultNumber = getResultNumber(connection); + logger.debug("Calculation of result set total number successful : resultNumber = " + resultNumber); + // ok, no need to ask the datareader to calculate the query total result number + dataReader.setCalculateResultNumberEnabled(false); + + } catch (Exception t) { + logger.debug("KO Calculation of result set total number using inlineview", t); + try { + logger.debug("Loading data using scrollable resultset tecnique"); + resultNumber = getResultNumber(resultSet); + logger.debug("OK data loaded using scrollable resultset tecnique : resultNumber = " + resultNumber); + dataReader.setCalculateResultNumberEnabled(false); + } catch (SQLException e) { + logger.debug("KO data loaded using scrollable resultset tecnique", e); + dataReader.setCalculateResultNumberEnabled(true); + } + } + } else { + logger.debug("Calculation of result set total number is NOT enabled"); + dataReader.setCalculateResultNumberEnabled(false); + } + + dataStore = null; + try { + // read data + dataStore = dataReader.read(resultSet); + } catch (Exception t) { + throw new SpagoBIRuntimeException("An error occurred while parsing resultset", t); + } + + if (resultNumber > -1) { // it means that resultNumber was successfully calculated by this data proxy + int limitedResultNumber = getMaxResults() > 0 && resultNumber > getMaxResults() ? getMaxResults() : resultNumber; + dataStore.getMetaData().setProperty("resultNumber", new Integer(limitedResultNumber)); + } + + } finally { + try { + releaseResources(connection, stmt, resultSet); + } catch (Exception t) { + throw new SpagoBIRuntimeException("Impossible to release allocated resources properly", t); + } + } + + return dataStore; + } + + @Override + protected int getResultNumber(Connection connection) { + logger.debug("IN"); + int resultNumber = 0; + Statement stmt = null; + + ResultSet rs = null; + + String statement = getStatement(); + // if db is SQL server the query nees to be modified in case it contains ORDER BY clause + + String dialect = dataSource.getHibDialectClass(); + logger.debug("Dialect is " + dialect); + + try { + String tableAlias = ""; + if (!dialect.toLowerCase().contains("orient")) { + tableAlias = "temptable"; + } + String sqlQuery = "SELECT COUNT(*) FROM (" + getOldStatement() + ") " + tableAlias; + logger.info("Executing query " + sqlQuery + " ..."); + stmt = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); + rs = stmt.executeQuery(sqlQuery); + rs.next(); + resultNumber = rs.getInt(1); + } catch (Throwable t) { + throw new SpagoBIRuntimeException("An error occurred while creating connection steatment", t); + } finally { + releaseResources(null, stmt, rs); + } + logger.debug("OUT : returning " + resultNumber); + return resultNumber; + } + + private String modifySQLServerQuery(String statement) { + logger.debug("IN"); + int selectIndex = statement.toUpperCase().indexOf("SELECT"); + String noSelect = statement.substring(selectIndex + 6); + logger.debug("No Select Query " + noSelect); + // remove spaces + noSelect = noSelect.trim(); + logger.debug("No Select trimmed query " + noSelect); + + int distinctIndex = noSelect.toUpperCase().indexOf("DISTINCT "); + boolean distinct = false; + if (distinctIndex == 0) { + logger.debug("Remove distinct clause"); + distinct = true; + noSelect = noSelect.substring(distinctIndex + 8); + noSelect = noSelect.trim(); + logger.debug("No dstinct trimmetd query " + noSelect); + } + + // remove also distinct if present + String prefix = ""; + if (distinct) { + prefix = "select distinct TOP(100) PERCENT "; + } else { + prefix = "select TOP(100) PERCENT "; + + } + statement = prefix + noSelect; + logger.debug("Statement for SQL SERVER " + statement); + return statement; + } + + @Override + protected int getResultNumber(ResultSet resultSet) throws SQLException { + logger.debug("IN"); + + int rowcount = 0; + if (resultSet.last()) { + rowcount = resultSet.getRow(); + resultSet.beforeFirst(); // not rs.first() because the rs.next() + // below will move on, missing the first + // element + } + + return rowcount; + } + + @Override + public IDataSource getDataSource() { + return dataSource; + } + + @Override + public void setDataSource(IDataSource dataSource) { + this.dataSource = dataSource; + } + + private void releaseResources(Connection connection, Statement statement, ResultSet resultSet) { + + logger.debug("IN"); + + try { + logger.debug("Relesing resources ..."); + if (resultSet != null) { + try { + resultSet.close(); + + } catch (SQLException e) { + throw new SpagoBIRuntimeException("Impossible to release [resultSet]", e); + } + logger.debug("[resultSet] released succesfully"); + } + + if (statement != null) { + try { + statement.close(); + + } catch (SQLException e) { + throw new SpagoBIRuntimeException("Impossible to release [statement]", e); + } + logger.debug("[statement] released succesfully"); + } + + if (connection != null) { + try { + if (!connection.isClosed()) { + connection.close(); + } + } catch (SQLException e) { + throw new SpagoBIRuntimeException("Impossible to release [connection]", e); + } + logger.debug("[connection] released succesfully"); + } + logger.debug("All resources have been released succesfully"); + } finally { + logger.debug("OUT"); + } + } + + @Override + public ResultSet getData(IDataReader dataReader, Object... resources) { + logger.debug("IN"); + Statement stmt = (Statement) resources[0]; + ResultSet resultSet = null; + try { + if (getMaxResults() > 0) { + stmt.setMaxRows(getMaxResults()); + } + String sqlQuery = getStatement(); + logger.info("Executing query " + sqlQuery + " ..."); + resultSet = stmt.executeQuery(sqlQuery); + return resultSet; + } catch (SQLException e) { + throw new SpagoBIRuntimeException(e); + } finally { + logger.debug("OUT"); + } + } + + @Override + public boolean isOffsetSupported() { + return true; + } + + @Override + public boolean isFetchSizeSupported() { + return true; + } + + @Override + public String getStatement() { + + if (fetchSize == -1) { + if (!this.statement.isEmpty()) { + this.statement = this.statement.replaceAll(";", ""); + return this.statement; + } + } + + String newStatement = ""; + if (!this.statement.isEmpty()) { + this.statement = this.statement.replaceAll(";", ""); + + String preQuery = "SELECT * FROM ("; + newStatement = preQuery.concat(this.statement).concat(") OFFSET " + offset + " LIMIT " + fetchSize); + } + + return newStatement; + } + + public String getOldStatement() { + return statement; + } + + @Override + public void setStatement(String statement) { + this.statement = statement; + } + + @Override + public int getFetchSize() { + return fetchSize; + } + + @Override + public void setFetchSize(int fetchSize) { + this.fetchSize = fetchSize; + } + + @Override + public int getOffset() { + return offset; + } + + @Override + public void setOffset(int offset) { + this.offset = offset; + } +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/RESTDataProxy.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/RESTDataProxy.java index 50933f6b8c7..06457adb2b4 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/RESTDataProxy.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/RESTDataProxy.java @@ -48,7 +48,7 @@ public class RESTDataProxy extends AbstractDataProxy { private static final int FETCH_SIZE_NOT_DEFINED = -1; private static final int MAX_RESULT_NOT_DEFINED = -1; - protected final String requestBody; + protected String requestBody; protected String address; protected final Map requestHeaders; protected final HttpMethod method; @@ -133,7 +133,7 @@ public IDataStore load(IDataReader dataReader) { } protected List getQuery() { - List res = new ArrayList(3); + List res = new ArrayList(); if (offsetParam != null) { if (offset != OFFSET_NOT_DEFINED) { res.add(new NameValuePair(offsetParam, Integer.toString(offset))); @@ -153,7 +153,7 @@ protected List getQuery() { } // ========= CREDIT: https://github.com/VivekKumar856 - if (this.parameters != null & this.parameters.size() > 0) { + if (this.parameters != null && this.parameters.size() > 0) { Iterator keys = this.parameters.keySet().iterator(); while (keys.hasNext()) { String key = (String) keys.next(); @@ -171,10 +171,6 @@ protected List getQuery() { return res; } - protected String setPaginationParameters(String address, IDataReader dataReader) { - return address; - } - public String getRequestBody() { return requestBody; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/SolrDataProxy.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/SolrDataProxy.java index 7c593810f24..150bc01e8f2 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/SolrDataProxy.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/dataproxy/SolrDataProxy.java @@ -43,38 +43,50 @@ public class SolrDataProxy extends RESTDataProxy { private static final Logger logger = Logger.getLogger(SolrDataProxy.class); private int maxRestConf = 999999; - public SolrDataProxy(String address, HttpMethod method, String facetField, Map requestHeaders, String offsetParam, String fetchSizeParam, + public SolrDataProxy(String address, HttpMethod method, String body, String facetField, Map requestHeaders, String offsetParam, String fetchSizeParam, String maxResultsParam, boolean facets) { - super(address, method, null, requestHeaders, offsetParam, fetchSizeParam, maxResultsParam, false); + super(address, method, body, requestHeaders, offsetParam, fetchSizeParam, maxResultsParam, false); this.facetField = facetField; this.facets = facets; } - @Override - protected String setPaginationParameters(String address, IDataReader dataReader) { + private String createPaginationParameters(IDataReader dataReader) { + StringBuilder paginationParam = new StringBuilder(); if (this.facets) { if (dataReader.isOffsetSupported() && dataReader.getOffset() > 0) { - address = address + "&facet.offset=" + dataReader.getOffset(); + paginationParam.append("&facet.offset=" + dataReader.getOffset()); } if (dataReader.isFetchSizeSupported() && dataReader.getFetchSize() > 0) { - address = address + "&facet.limit=" + dataReader.getFetchSize(); + paginationParam.append("&facet.limit=" + dataReader.getFetchSize()); } } else { if (dataReader.isOffsetSupported() && dataReader.getOffset() > 0) { - address = address + "&start=" + dataReader.getOffset(); + paginationParam.append("&start=" + dataReader.getOffset()); } + paginationParam.append("&rows="); if (dataReader.isFetchSizeSupported() && dataReader.getFetchSize() > 0) { - address = address + "&rows=" + dataReader.getFetchSize(); + paginationParam.append(dataReader.getFetchSize()); } else if (dataReader.isMaxResultsSupported() && dataReader.getMaxResults() > 0) { - address = address + "&rows=" + dataReader.getMaxResults(); + paginationParam.append(dataReader.getMaxResults()); } else { - address = address + "&rows=" + maxRestConf; + paginationParam.append(maxRestConf); } } - return address; + + return paginationParam.toString(); + + } + + private void addPaginationParams(IDataReader dataReader) { + String paginationParam = createPaginationParameters(dataReader); + if (method == HttpMethod.Get) { + this.address += paginationParam; + } else if (method == HttpMethod.Post) { + this.requestBody += paginationParam; + } } @@ -82,8 +94,8 @@ protected String setPaginationParameters(String address, IDataReader dataReader) public IDataStore load(IDataReader dataReader) { if (!facets) { this.address = this.address.replaceAll(" ", "%20"); - logger.info("SOLR QUERY TO EXECUTE [" + setPaginationParameters(address, dataReader) + "]"); - this.address = setPaginationParameters(address, dataReader); + addPaginationParams(dataReader); + logger.info("Solr query to execute has address [" + address + "] and body [" + requestBody + "]"); return super.load(dataReader); } else { try { @@ -92,10 +104,16 @@ public IDataStore load(IDataReader dataReader) { List query = getQuery(); String tempAddress = this.address.replaceAll(" ", "%20"); - logger.debug("SOLR QUERY TO EXECUTE [" + setPaginationParameters(tempAddress, dataReader) + "]"); + String tempBody = this.requestBody; + if (method == HttpMethod.Get) { + tempAddress += createPaginationParameters(dataReader); + } else if (method == HttpMethod.Post) { + tempBody += createPaginationParameters(dataReader); + } + logger.info("Solr query to execute has address [" + tempAddress + "] and body [" + tempBody + "]"); - Response response = RestUtilities.makeRequest(this.method, setPaginationParameters(tempAddress, dataReader), this.requestHeaders, - this.requestBody, query); + Response response = RestUtilities.makeRequest(this.method, tempAddress, this.requestHeaders, + tempBody, query); String responseBody = response.getResponseBody(); if (response.getStatusCode() != HttpStatus.SC_OK) { throw new RESTDataProxyException( diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/CompositeSolrDataReader.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/CompositeSolrDataReader.java index ef7b9c50a5b..06957d98762 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/CompositeSolrDataReader.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/CompositeSolrDataReader.java @@ -18,33 +18,36 @@ */ package it.eng.spagobi.tools.dataset.common.datareader; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.solr.SolrDataStore; -import org.apache.log4j.Logger; - import java.util.ArrayList; import java.util.List; +import org.apache.log4j.Logger; + +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; +import it.eng.spagobi.tools.dataset.solr.SolrDataStore; + public class CompositeSolrDataReader extends SolrDataReader { - static private Logger logger = Logger.getLogger(CompositeSolrDataReader.class); + static private Logger logger = Logger.getLogger(CompositeSolrDataReader.class); - private List facetSolrDataReaders = new ArrayList<>(); + private List facetSolrDataReaders = new ArrayList<>(); - public CompositeSolrDataReader(SolrDataReader dataReader) { - super(dataReader.getJsonPathItems(), dataReader.getJsonPathAttributes()); - } + public CompositeSolrDataReader(SolrDataReader dataReader) { + super(dataReader.getJsonPathItems(), dataReader.getJsonPathAttributes()); + } - @Override - public IDataStore read(Object data) { - SolrDataStore result = new SolrDataStore(super.read(data)); - for (FacetSolrDataReader dataReader : facetSolrDataReaders) { - result.addFacetDataStore(dataReader.getFacetField(), dataReader.read(data)); - } - return result; - } + @Override + public IDataStore read(Object data) { + SolrDataStore result = new SolrDataStore(super.read(data)); + if (result.getRecordsCount() > 0) { + for (FacetSolrDataReader dataReader : facetSolrDataReaders) { + result.addFacetDataStore(dataReader.getFacetField(), dataReader.read(data)); + } + } + return result; + } - public void addFacetSolrDataReader(FacetSolrDataReader dataReader) { - facetSolrDataReaders.add(dataReader); - } + public void addFacetSolrDataReader(FacetSolrDataReader dataReader) { + facetSolrDataReaders.add(dataReader); + } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/FileDatasetCsvDataReader.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/FileDatasetCsvDataReader.java index e4b224003bf..35a55747166 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/FileDatasetCsvDataReader.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/FileDatasetCsvDataReader.java @@ -171,7 +171,6 @@ private DataStore readWithCsvMapReader(InputStream inputDataStream) throws Excep FieldMetadata fieldMeta = new FieldMetadata(); String fieldName = StringUtils.escapeForSQLColumnName(header[i]); fieldMeta.setName(fieldName); - fieldMeta.setType(String.class); dataStoreMeta.addFiedMeta(fieldMeta); } @@ -199,6 +198,7 @@ private DataStore readWithCsvMapReader(InputStream inputDataStream) throws Excep && (!checkMaxResults || (rowFetched - offset < maxResults)))) { // Create Datastore data IRecord record = new Record(dataStore); + FieldMetadata meta; for (int i = 0; i < header.length; i++) { logger.debug(header[i] + " = " + contentsMap.get(header[i])); @@ -209,37 +209,49 @@ private DataStore readWithCsvMapReader(InputStream inputDataStream) throws Excep field = new Field(contentsMap.get(header[i])); // update metadata type in order with the real value's type (default was string) if (NumberUtils.isNumber((String) field.getValue())) { - ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)).setType(BigDecimal.class); + meta = ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)); + meta.setType(getNewMetaType(meta.getType(), BigDecimal.class)); field.setValue(new BigDecimal(String.valueOf(field.getValue()))); } // check if it's a number using comma decimal separator else if (NumberUtils.isNumber(((String) field.getValue()).replace(",", "."))) { - ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)).setType(BigDecimal.class); + meta = ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)); + meta.setType(getNewMetaType(meta.getType(), BigDecimal.class)); field.setValue(new BigDecimal(((String) field.getValue()).replace(",", "."))); } // check if it's a Date else { + boolean isDate = false; + boolean isTimestamp = false; try { DateTimeFormatter formatter = DateTimeFormat.forPattern(dateFormat); LocalDate localDate = LocalDate.parse((String) field.getValue(), formatter); // Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); Date date = localDate.toDate(); - ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)).setType(Date.class); + meta = ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)); + meta.setType(getNewMetaType(meta.getType(), Date.class)); field.setValue(date); + isDate = true; } catch (Exception ex) { logger.debug((String) field.getValue() + " is not a date"); } - + // check if it's a Timestamp try { DateTimeFormatter formatter = DateTimeFormat.forPattern(timestampFormat); LocalDateTime localDateTime = LocalDateTime.parse(field.getValue().toString(), formatter); DateTime datetime = localDateTime.toDateTime(); Timestamp timestamp = new Timestamp(datetime.getMillis()); - dataStore.getMetaData().getFieldMeta(i).setType(Timestamp.class); + meta = ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)); + meta.setType(getNewMetaType(meta.getType(), Timestamp.class)); field.setValue(timestamp); + isTimestamp = true; } catch (Exception e) { logger.debug(field.getValue().toString() + " is not a timestamp"); } + // if it's nothing of the previous then it's a string + if (!isDate && !isTimestamp) { + ((FieldMetadata) dataStore.getMetaData().getFieldMeta(i)).setType(String.class); + } } } record.appendField(field); @@ -266,6 +278,13 @@ else if (NumberUtils.isNumber(((String) field.getValue()).replace(",", "."))) { return dataStore; } + private Class getNewMetaType(Class oldType, Class newType) { + if (oldType == String.class) + return String.class; + else + return newType; + } + @Override public boolean isOffsetSupported() { return true; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JDBCStandardDataReader.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JDBCStandardDataReader.java index 8ce23e41793..1ca8338cc67 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JDBCStandardDataReader.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JDBCStandardDataReader.java @@ -1,5 +1,5 @@ /* - * Knowage, Open Source Business Intelligence suite ++ * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. * * Knowage is free software: you can redistribute it and/or modify @@ -17,6 +17,11 @@ */ package it.eng.spagobi.tools.dataset.common.datareader; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.apache.log4j.Logger; + import it.eng.spago.error.EMFInternalError; import it.eng.spago.error.EMFUserError; import it.eng.spagobi.tools.dataset.common.datastore.DataStore; @@ -29,11 +34,6 @@ import it.eng.spagobi.tools.dataset.common.metadata.MetaData; import it.eng.spagobi.utilities.assertion.Assert; -import java.sql.ResultSet; -import java.sql.SQLException; - -import org.apache.log4j.Logger; - /** * @author Andrea Gioia (andrea.gioia@eng.it) */ diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JSONPathDataReader.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JSONPathDataReader.java index fb9620e3ab8..f56124484ff 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JSONPathDataReader.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/JSONPathDataReader.java @@ -28,18 +28,14 @@ import java.util.Arrays; import java.util.Date; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.TreeSet; import org.apache.log4j.Logger; import org.joda.time.Instant; import org.json.JSONException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.PathNotFoundException; @@ -197,7 +193,7 @@ private static boolean isJSONArray(String responseBody) { } @Override - public synchronized IDataStore read(Object data) { + public IDataStore read(Object data) { Helper.checkNotNull(data, "data"); if (!(data instanceof String)) { throw new IllegalArgumentException("data must be a string"); @@ -288,8 +284,13 @@ protected void addData(String data, IDataStore dataStore, IMetaData dataStoreMet } Assert.assertNotNull(type != null, "type!=null"); - IField field = new Field(getValue(value, fm)); - record.appendField(field); + try { + IField field = new Field(getValue(value, fm)); + record.appendField(field); + } catch (Exception e) { + String msg = String.format("Error getting value for field %s", fm.getName()); + throw new IllegalStateException(msg, e); + } } if (useDirectlyAttributes) { manageDirectlyAttributes(o, record, dataStoreMeta, dataStore); @@ -404,7 +405,7 @@ private static Object normalizeNumber(Object value) { return value; } - private static Object getJSONPathValue(Object o, String jsonPathValue) throws JSONException { + protected Object getJSONPathValue(Object o, String jsonPathValue) throws JSONException { // can be an array with a single value, a single object or also null (not found) Object res = null; try { @@ -452,7 +453,7 @@ private static Object getJSONFormat(Object res) { return res; } - public synchronized int getIdFieldIndex() { + public int getIdFieldIndex() { if (idFieldIndex == -2) { // not set if (ngsiDefaultItems && !dataReadFirstTime) { @@ -478,10 +479,9 @@ public synchronized int getIdFieldIndex() { protected void addFieldMetadata(IMetaData dataStoreMeta, List parsedData) { boolean idSet = false; - if (ngsiDefaultItems) + if (ngsiDefaultItems) { manageNGSI(parsedData); - else - manageNonNGSIObject(parsedData); + } for (int index = 0; index < jsonPathAttributes.size(); index++) { JSONPathAttribute jpa = jsonPathAttributes.get(index); @@ -489,7 +489,7 @@ protected void addFieldMetadata(IMetaData dataStoreMeta, List parsedData String header = jpa.name; boolean multiValue = jpa.multivalue; fm.setAlias(getAlias(header)); - fm.setName(header); + fm.setName(getName(header)); fm.setMultiValue(multiValue); if (ID_NAME.equalsIgnoreCase(header)) { if (idSet) { @@ -520,6 +520,10 @@ protected String getAlias(String name) { return name; } + protected String getName(String name) { + return name; + } + private void manageNGSI(List parsedData) { if (ngsiDefaultItems && !dataReadFirstTime) { List ngsiAttributes = getNGSIAttributes(parsedData); @@ -528,32 +532,6 @@ private void manageNGSI(List parsedData) { dataReadFirstTime = true; } - private void manageNonNGSIObject(List parsedData) { - if (!ngsiDefaultItems && !dataReadFirstTime) { - // If a column contains an Object then cast to a JSON string - - for (Object r : parsedData) { - LinkedHashMap record = (LinkedHashMap) r; - Set columnNames = record.keySet(); - for (Object column : columnNames) { - Object obj = record.get(column); - if (obj instanceof Map) { - ObjectMapper mapper = new ObjectMapper(); - try { - obj = mapper.writeValueAsString(obj); - } catch (JsonProcessingException e) { - System.out.println("Impossible to parse JSON"); - e.printStackTrace(); - } - // obj = new Gson().toJson(obj,LinkedHashMap.class); - record.put(column, obj); - } - } - } - } - dataReadFirstTime = true; - } - private void updateAttributes(List ngsiAttributes) { Map localByName = new HashMap(jsonPathAttributes.size()); for (JSONPathAttribute jpa : jsonPathAttributes) { @@ -610,10 +588,8 @@ private static Object getSingleValue(String value, IFieldMetaData fmd) throws Pa return Short.valueOf(value); } else if (fieldType.equals(Integer.class)) { /* - * In Solr, an integer value like the number "7" - * is returned as a value like "7.0": a good - * way to prevent problems in this case is to - * use the following. + * In Solr, an integer value like the number "7" is returned as a value like "7.0": a good way to prevent problems in this case is to use the + * following. */ return new BigDecimal(value).intValue(); } else if (fieldType.equals(BigInteger.class)) { @@ -790,7 +766,7 @@ public String getJsonPathItems() { return jsonPathItems; } - public synchronized List getJsonPathAttributes() { + public List getJsonPathAttributes() { if (ngsiDefaultItems && !dataReadFirstTime) { throw new IllegalStateException("NGSI Rest Data Reader needs a first read of data"); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/SolrFacetPivotDataReader.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/SolrFacetPivotDataReader.java index 31493c2746b..1c069f9823e 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/SolrFacetPivotDataReader.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datareader/SolrFacetPivotDataReader.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,6 +34,9 @@ import org.json.JSONException; import org.json.JSONObject; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.PathNotFoundException; + import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; import it.eng.spagobi.utilities.assertion.Assert; import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; @@ -272,8 +276,42 @@ private void update(JSONObject jsonObject) { jsonPathAttributes.addAll(newJsonPathAttributes); } + public K getKey(Map map, V value) { + for (Entry entry : map.entrySet()) { + if (entry.getValue().equals(value)) { + return entry.getKey(); + } + } + return null; + } + @Override protected String getAlias(String name) { return nameToAliasMap.containsKey(name) ? nameToAliasMap.get(name) : name; } + + @Override + protected String getName(String name) { + return nameToAliasMap.containsValue(name) ? getKey(nameToAliasMap, name) : name; + } + + @Override + protected Object getJSONPathValue(Object o, String jsonPathValue) throws JSONException { + // can be an array with a single value, a single object or also null (not found) + Object res = null; + try { + if (jsonPathValue.contains(" ")) { + String initial = "$."; + jsonPathValue = jsonPathValue.substring(jsonPathValue.indexOf("$") + 2); + jsonPathValue = "['" + jsonPathValue + "']"; + res = JsonPath.read(o, initial.concat(jsonPathValue)); + } else { + res = JsonPath.read(o, jsonPathValue); + } + } catch (PathNotFoundException e) { + logger.debug("JPath not found " + jsonPathValue); + } + + return res; + } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datawriter/JSONDataWriter.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datawriter/JSONDataWriter.java index 653def0c4d3..6cac0fbf3ab 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datawriter/JSONDataWriter.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/common/datawriter/JSONDataWriter.java @@ -17,8 +17,10 @@ */ package it.eng.spagobi.tools.dataset.common.datawriter; +import java.io.Reader; import java.math.BigDecimal; import java.math.BigInteger; +import java.sql.Clob; import java.sql.Time; import java.sql.Timestamp; import java.text.SimpleDateFormat; @@ -42,6 +44,7 @@ import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; import it.eng.spagobi.tools.dataset.solr.SolrDataStore; import it.eng.spagobi.utilities.assertion.Assert; +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; /** * @author Andrea Gioia (andrea.gioia@eng.it) @@ -237,7 +240,7 @@ protected Object getFieldValue(IField field, IFieldMetaData fieldMetaData) { if (preserveOriginalDataTypes) { Object toReturn; - if (BigDecimal.class.isAssignableFrom(fieldMetaData.getType())) { + if (BigDecimal.class.isAssignableFrom(fieldMetaData.getType()) && field.getValue() != null) { toReturn = Float.parseFloat(field.getValue().toString()); } else { toReturn = field.getValue(); @@ -261,10 +264,29 @@ protected Object getFieldValue(IField field, IFieldMetaData fieldMetaData) { result = CACHE_TIMEONLY_FORMATTER.format(field.getValue()); } else if (Date.class.isAssignableFrom(fieldMetaData.getType())) { result = DATE_FORMATTER.format(field.getValue()); + } else if (Boolean.class.isAssignableFrom(fieldMetaData.getType())) { + result = Boolean.valueOf(field.getValue().toString()); + } else if (Byte.class.isAssignableFrom(fieldMetaData.getType())) { + result = Byte.valueOf(field.getValue().toString()); + } else if (Short.class.isAssignableFrom(fieldMetaData.getType())) { + result = Short.valueOf(field.getValue().toString()); + } else if (Integer.class.isAssignableFrom(fieldMetaData.getType())) { + result = Integer.valueOf(field.getValue().toString()); + } else if (Long.class.isAssignableFrom(fieldMetaData.getType())) { + result = Long.valueOf(field.getValue().toString()); + } else if (BigInteger.class.isAssignableFrom(fieldMetaData.getType())) { + result = new BigInteger(field.getValue().toString()); + } else if (Float.class.isAssignableFrom(fieldMetaData.getType())) { + result = Float.valueOf(field.getValue().toString()); + } else if (Double.class.isAssignableFrom(fieldMetaData.getType())) { + result = Double.valueOf(field.getValue().toString()); + } else if (BigDecimal.class.isAssignableFrom(fieldMetaData.getType())) { + result = new BigDecimal(field.getValue().toString()); } else { result = field.getValue().toString(); } } + return result; } @@ -348,6 +370,25 @@ record = (IRecord) records.next(); String fieldName = adjust ? fieldMetaData.getName() : getFieldName(fieldMetaData, j++); Object fieldValue = getFieldValue(field, fieldMetaData); + + try { + if (oracle.jdbc.OracleClob.class.isAssignableFrom(fieldMetaData.getType()) + || oracle.sql.CLOB.class.isAssignableFrom(fieldMetaData.getType())) { // Can we add a limit? + Reader r = ((Clob) field.getValue()).getCharacterStream(); + StringBuffer buffer = new StringBuffer(); + int ch; + while ((ch = r.read()) != -1) { + buffer.append("" + (char) ch); + } + fieldValue = buffer.toString(); + } // provided + } catch (NoClassDefFoundError t) { + logger.debug("Class not found error", t); + } catch (Exception e) { + logger.error("An unpredicted error occurred at recno [" + recNo + "] while serializing dataStore", e); + throw new SpagoBIRuntimeException("An unpredicted error occurred at recno [" + recNo + "] while serializing dataStore", e); + } + if (fieldValue == null) { recordJSON.put(fieldName, ""); } else { @@ -356,6 +397,7 @@ record = (IRecord) records.next(); } recordsJSON.put(recordJSON); + } } catch (Throwable t) { @@ -433,6 +475,7 @@ private Object write(IMetaData metadata) { } else { logger.debug("Column [" + (i + 1) + "] class is equal to [" + clazz.getName() + "]"); } + if (Number.class.isAssignableFrom(clazz)) { // BigInteger, Integer, Long, Short, Byte if (Integer.class.isAssignableFrom(clazz) || BigInteger.class.isAssignableFrom(clazz) || Long.class.isAssignableFrom(clazz) diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DataSetConstants.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DataSetConstants.java index 6fae20779d5..38f5c5a3d09 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DataSetConstants.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DataSetConstants.java @@ -90,7 +90,7 @@ public class DataSetConstants { public static final String FEDERATED = "Federated"; public static final String FLAT = "Flat"; public static final String DS_REST_NAME = "REST"; - public static final String DS_PYTHON_NAME = "Python"; + public static final String DS_PYTHON_NAME = "Python/R"; public static final String DS_SOLR_NAME = "Solr"; public static final String SPARQL = "SPARQL"; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DatasetFunctionsConfig.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DatasetFunctionsConfig.java new file mode 100644 index 00000000000..6049273480d --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/DatasetFunctionsConfig.java @@ -0,0 +1,54 @@ +package it.eng.spagobi.tools.dataset.constants; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import it.eng.spagobi.tools.dataset.metasql.query.DatabaseDialect; + +public class DatasetFunctionsConfig { + + private static final String AVAILABLE_FUNCTIONS = "availableFunctions"; + private static final String NULLIF_FUNCTION = "nullifFunction"; + private static final String NULLIF = "NULLIF"; + HashMap>> functionsConfigurationMap = new HashMap>>(); + + public DatasetFunctionsConfig() { + List availableFunctions = new ArrayList(); + HashMap> map = new HashMap>(); + List list = new ArrayList(); + + functionsConfigurationMap.put(DatabaseDialect.HIVE.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.CASSANDRA.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.ORIENT.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.METAMODEL.getValue(), map); + + list.add(NULLIF); + map.put(NULLIF_FUNCTION, list); + availableFunctions.add(NULLIF); + map.put(AVAILABLE_FUNCTIONS, availableFunctions); + + functionsConfigurationMap.put(DatabaseDialect.HIVE2.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.MONGO.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.DB2.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.IMPALA.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.MYSQL.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.ORACLE_9I10G.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.ORACLE.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.POSTGRESQL.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.SPARKSQL.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.SQLSERVER.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.ORACLE_SPATIAL.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.TERADATA.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.VERTICA.getValue(), map); + functionsConfigurationMap.put(DatabaseDialect.REDSHIFT.getValue(), map); + } + + public List getAvailableFunctions(String dialect) { + return functionsConfigurationMap.get(dialect).get(AVAILABLE_FUNCTIONS); + } + + public List getNullifFunction(String dialect) { + return functionsConfigurationMap.get(dialect).get(NULLIF_FUNCTION); + } +} \ No newline at end of file diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/PythonDataSetConstants.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/PythonDataSetConstants.java index 9c5da846ec2..7ceefcff511 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/PythonDataSetConstants.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/constants/PythonDataSetConstants.java @@ -27,6 +27,7 @@ public class PythonDataSetConstants { public static final String[] REST_JSON_OBJECT_ATTRIBUTES = { REST_REQUEST_HEADERS }; public static final String REST_REQUEST_BODY = "restRequestBody"; public static final String PYTHON_ENVIRONMENT = "pythonEnvironment"; + public static final String PYTHON_DATASET_TYPE = "pythonDatasetType"; public static final String PYTHON_SCRIPT = "pythonScript"; public static final String PYTHON_DATAFRAME_NAME = "dataframeName"; public static final String PYTHON_SCRIPT_PARAMETERS = "pars"; @@ -36,7 +37,7 @@ public class PythonDataSetConstants { public static final String REST_OFFSET = "restOffset"; public static final String REST_FETCH_SIZE = "restFetchSize"; public static final String REST_MAX_RESULTS = "restMaxResults"; - public static final String[] PYTHON_STRING_ATTRIBUTES = { PYTHON_ADDRESS, PYTHON_ENVIRONMENT, PYTHON_SCRIPT, PYTHON_DATAFRAME_NAME, + public static final String[] PYTHON_STRING_ATTRIBUTES = { PYTHON_ADDRESS, PYTHON_ENVIRONMENT, PYTHON_SCRIPT, PYTHON_DATAFRAME_NAME, PYTHON_DATASET_TYPE, PYTHON_SCRIPT_PARAMETERS, REST_REQUEST_BODY, REST_JSON_PATH_ITEMS, REST_JSON_DIRECTLY_ATTRIBUTES, REST_OFFSET, REST_FETCH_SIZE, REST_MAX_RESULTS }; public static final String[] PYTHON_ALL_ATTRIBUTES = new String[PYTHON_STRING_ATTRIBUTES.length + REST_JSON_OBJECT_ATTRIBUTES.length + REST_JSON_ARRAY_ATTRIBUTES.length]; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/DatabaseDialect.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/DatabaseDialect.java index 08668a47ba5..ee43938a93b 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/DatabaseDialect.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/DatabaseDialect.java @@ -27,21 +27,26 @@ @JsonFormat(shape = JsonFormat.Shape.OBJECT) public enum DatabaseDialect { - HIVE("Apache Hive v1", "hive", true, false, false, true), HIVE2("Apache Hive v2", "org.hibernate.dialect.MySQLDialect", true, false, false, true), MONGO( - "MongoDB", "MongoDialect", false, false, false, false), CASSANDRA("Apache Cassandra", "org.hibernate.dialect.cassandra", true, false, false, - false), DB2("IBM DB2", "org.hibernate.dialect.DB2400Dialect", true, true, false, false), IMPALA("Apache Impala", - "org.hibernate.dialect.impala", true, true, false, - true), MYSQL("MySQL/MariaDB", "org.hibernate.dialect.MySQLInnoDBDialect", true, true, true, true), ORACLE_9I10G("Oracle 9i/10g", - "org.hibernate.dialect.Oracle9Dialect", true, true, true, - true), ORACLE("Oracle", "org.hibernate.dialect.OracleDialect", true, true, true, true), POSTGRESQL("PostgreSQL", - "org.hibernate.dialect.PostgreSQLDialect", true, true, true, - true), SPARKSQL("Apache Spark SQL", "org.hibernate.dialect.sparksql", true, false, false, true), SQLSERVER( - "Microsoft SQL Server", "org.hibernate.dialect.SQLServerDialect", true, true, false, - true), ORACLE_SPATIAL("Oracle Database Spatial", "org.hibernatespatial.oracle.CustomOracleSpatialDialect", - true, true, true, true), ORIENT("OrientDB", "orient", true, true, false, true), TERADATA("Teradata", - "org.hibernate.dialect.TeradataDialect", true, true, false, true), VERTICA("Vertica", - "org.hibernate.dialect.VerticaDialect", true, true, true, - true), METAMODEL("MetaModelDialect", "metamodel", true, false, false, true); + // @formatter:off + HIVE("Apache Hive v1", "hive", true, false, false, true), + HIVE2("Apache Hive v2", "org.hibernate.dialect.MySQLDialect", true, false, false, true), + MONGO("MongoDB", "MongoDialect", false, false, false, false), + CASSANDRA("Apache Cassandra", "org.hibernate.dialect.cassandra", true, false, false,false), + DB2("IBM DB2", "org.hibernate.dialect.DB2400Dialect", true, true, false, false), + IMPALA("Apache Impala","org.hibernate.dialect.impala", true, true, false,true), + MYSQL("MySQL/MariaDB", "org.hibernate.dialect.MySQLInnoDBDialect", true, true, true, true), + ORACLE_9I10G("Oracle 9i/10g","org.hibernate.dialect.Oracle9Dialect", true, true, true, true), + ORACLE("Oracle", "org.hibernate.dialect.OracleDialect", true, true, true, true), + POSTGRESQL("PostgreSQL","org.hibernate.dialect.PostgreSQLDialect", true, true, true, true), + SPARKSQL("Apache Spark SQL", "org.hibernate.dialect.sparksql", true, false, false, true), + SQLSERVER("Microsoft SQL Server", "org.hibernate.dialect.SQLServerDialect", true, true, false, true), + ORACLE_SPATIAL("Oracle Database Spatial", "org.hibernatespatial.oracle.CustomOracleSpatialDialect", true, true, true, true), + ORIENT("OrientDB", "orient", true, true, false, true), + TERADATA("Teradata","org.hibernate.dialect.TeradataDialect", true, true, false, true), + VERTICA("Vertica", "org.hibernate.dialect.VerticaDialect", true, true, true, true), + METAMODEL("MetaModelDialect", "metamodel", true, false, false, true), + REDSHIFT("Amazon RedShift","org.hibernate.dialect.RedShiftDialect", true, true, true, true); + // @formatter:on private final static HashMap dialects = new HashMap<>(DatabaseDialect.values().length); diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/AbstractSelectionField.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/AbstractSelectionField.java index e0dd6c58ff2..689e5358f4f 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/AbstractSelectionField.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/AbstractSelectionField.java @@ -20,6 +20,14 @@ public abstract class AbstractSelectionField { + protected String name; + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DataStoreCalculatedField.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DataStoreCalculatedField.java index 98e0ede406e..c01e2ac8627 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DataStoreCalculatedField.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DataStoreCalculatedField.java @@ -8,7 +8,6 @@ public class DataStoreCalculatedField extends AbstractCalculatedField { private IDataSet dataSet; - private String name; private String alias; private List projectionsList; private String formula; @@ -36,11 +35,17 @@ public DataStoreCalculatedField(IAggregationFunction aggregationFunction, IDataS this(aggregationFunction, dataSet, columnName, columnName, null); } + public DataStoreCalculatedField(IAggregationFunction aggregationFunction, IDataSet dataSet, String columnName, String alias) { + this(aggregationFunction, dataSet, columnName, alias, null); + } + public DataStoreCalculatedField(IAggregationFunction aggregationFunction, IDataSet dataSet, String columnName, String alias, String formula) { this.aggregationFunction = aggregationFunction; this.dataSet = dataSet; + this.name = columnName; + // IFieldMetaData fieldMetaData = DataSetUtilities.getFieldMetaData(dataSet, columnName); // if (columnName.contains(AbstractDataBase.STANDARD_ALIAS_DELIMITER)) { @@ -69,10 +74,12 @@ public void setDataSet(IDataSet dataSet) { this.dataSet = dataSet; } + @Override public String getName() { return name; } + @Override public void setName(String name) { this.name = name; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DatasetCalculatedField.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DatasetCalculatedField.java index de41a94df31..630c4bab0ac 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DatasetCalculatedField.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/DatasetCalculatedField.java @@ -10,7 +10,6 @@ public class DatasetCalculatedField extends AbstractCalculatedField { private IAggregationFunction aggregationFunction; private IDataSet dataSet; - private String name; private String alias; @SuppressWarnings("rawtypes") private Class type; diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Projection.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Projection.java index d41bbb36759..e9bf9ef7eb2 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Projection.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Projection.java @@ -9,7 +9,6 @@ public class Projection extends AbstractSelectionField { private IAggregationFunction aggregationFunction; private IDataSet dataSet; - private String name; private String alias; @SuppressWarnings("rawtypes") private Class type; @@ -70,7 +69,7 @@ public IDataSet getDataset() { return dataSet; } - public boolean hasAlias(){ + public boolean hasAlias() { return alias != null; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/SimpleSelectionField.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/SimpleSelectionField.java new file mode 100644 index 00000000000..7b8b976f80b --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/SimpleSelectionField.java @@ -0,0 +1,5 @@ +package it.eng.spagobi.tools.dataset.metasql.query.item; + +public class SimpleSelectionField extends AbstractSelectionField { + +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Sorting.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Sorting.java index f4f5ea146a9..7a55e9e4e9f 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Sorting.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/item/Sorting.java @@ -23,7 +23,7 @@ public class Sorting { - private Projection projection; + private AbstractSelectionField projection; private boolean isAscending; public Sorting(IDataSet dataSet, String columnAliasOrName, boolean isAscending) { @@ -39,7 +39,12 @@ public Sorting(Projection projection, boolean isAscending) { this.isAscending = isAscending; } - public Projection getProjection() { + public Sorting(AbstractSelectionField projection, boolean isAscending) { + this.projection = projection; + this.isAscending = isAscending; + } + + public AbstractSelectionField getProjection() { return projection; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/AbstractSelectQueryVisitor.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/AbstractSelectQueryVisitor.java index b7a0aeedc0c..d8b25b0700c 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/AbstractSelectQueryVisitor.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/AbstractSelectQueryVisitor.java @@ -393,20 +393,39 @@ public boolean isCalculatedColumn(String columnName) { protected void append(Sorting item) { String aliasDelimiter = database.getAliasDelimiter(); - Projection projection = item.getProjection(); - IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + AbstractSelectionField projs = item.getProjection(); - String name = projection.getName(); - String columnName = isCalculatedColumn(name) ? name.replace(AbstractDataBase.STANDARD_ALIAS_DELIMITER, aliasDelimiter) - : aliasDelimiter + name + aliasDelimiter; + if (!projs.getClass().equals(DataStoreCalculatedField.class)) { + Projection projection = (Projection) projs; + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); - if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { - queryBuilder.append(columnName); + String name = projection.getName(); + String columnName = isCalculatedColumn(name) ? name.replace(AbstractDataBase.STANDARD_ALIAS_DELIMITER, aliasDelimiter) + : aliasDelimiter + name + aliasDelimiter; + + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(columnName); + } else { + queryBuilder.append(aggregationFunction.apply(columnName)); + } + + queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); } else { - queryBuilder.append(aggregationFunction.apply(columnName)); - } + DataStoreCalculatedField projection = (DataStoreCalculatedField) projs; + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + + String name = projection.getAlias(); + String columnName = isCalculatedColumn(name) ? name.replace(AbstractDataBase.STANDARD_ALIAS_DELIMITER, aliasDelimiter) + : aliasDelimiter + name + aliasDelimiter; - queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(columnName); + } else { + queryBuilder.append(aggregationFunction.apply(columnName)); + } + + queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); + } } @Override @@ -481,20 +500,41 @@ protected void buildSelect(SelectQuery query) { List sortings = query.getSortings(); if (groups != null && !groups.isEmpty() && sortings != null && !sortings.isEmpty()) { for (Sorting sorting : sortings) { - Projection projection = sorting.getProjection(); + AbstractSelectionField projs = sorting.getProjection(); boolean projectionAlreadyDefined = false; - for (Projection p : projections) { - if (p.getDataset().equals(projection.getDataset()) && p.getName().equals(projection.getName())) { - projectionAlreadyDefined = true; - break; + if (!projs.getClass().equals(DataStoreCalculatedField.class)) { + Projection projection = (Projection) projs; + + for (Projection p : projections) { + if (p.getDataset().equals(projection.getDataset()) && p.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } } - } - if (!projectionAlreadyDefined) { - IAggregationFunction aggregationFunction = projection.getAggregationFunction(); - if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { - queryBuilder.append(","); - append(projection, false); + if (!projectionAlreadyDefined) { + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(","); + append(projection, false); + } + } + + } else { + DataStoreCalculatedField projection = (DataStoreCalculatedField) projs; + for (DataStoreCalculatedField p : projectionsCalcFields) { + if (p.getDataset().equals(projection.getDataset()) && p.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } } + if (!projectionAlreadyDefined) { + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(","); + append(projection, false); + } + } + } } } @@ -556,30 +596,63 @@ protected void buildGroupBy(SelectQuery query) { List sortings = query.getSortings(); if (sortings != null && !sortings.isEmpty()) { for (Sorting sorting : sortings) { - Projection projection = sorting.getProjection(); - boolean projectionAlreadyDefined = false; - for (AbstractSelectionField g : groups) { - if (g instanceof Projection) { - Projection proj = (Projection) g; - if (proj.getDataset().equals(projection.getDataset()) && proj.getName().equals(projection.getName())) { - projectionAlreadyDefined = true; - break; + AbstractSelectionField projs = sorting.getProjection(); + + if (!projs.getClass().equals(DataStoreCalculatedField.class)) { + Projection projection = (Projection) projs; + boolean projectionAlreadyDefined = false; + for (AbstractSelectionField g : groups) { + if (g instanceof Projection) { + Projection proj = (Projection) g; + if (proj.getDataset().equals(projection.getDataset()) && proj.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } + } else { + DataStoreCalculatedField calc = (DataStoreCalculatedField) g; + if (calc.getDataset().equals(projection.getDataset()) && calc.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } } - } else { - DataStoreCalculatedField calc = (DataStoreCalculatedField) g; - if (calc.getDataset().equals(projection.getDataset()) && calc.getName().equals(projection.getName())) { - projectionAlreadyDefined = true; - break; + } + if (!projectionAlreadyDefined) { + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(","); + append(projection, false); } } - } - if (!projectionAlreadyDefined) { - IAggregationFunction aggregationFunction = projection.getAggregationFunction(); - if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { - queryBuilder.append(","); - append(projection, false); + + } else { + + DataStoreCalculatedField projection = (DataStoreCalculatedField) projs; + boolean projectionAlreadyDefined = false; + for (AbstractSelectionField g : groups) { + if (g instanceof Projection) { + Projection proj = (Projection) g; + if (proj.getDataset().equals(projection.getDataset()) && proj.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } + } else { + DataStoreCalculatedField calc = (DataStoreCalculatedField) g; + if (calc.getDataset().equals(projection.getDataset()) && calc.getName().equals(projection.getName())) { + projectionAlreadyDefined = true; + break; + } + } + } + if (!projectionAlreadyDefined) { + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + // queryBuilder.append(","); + // append(projection, false); + } } + } + } } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/OracleSelectQueryVisitor.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/OracleSelectQueryVisitor.java index 21e432bfeb4..a7d3471b075 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/OracleSelectQueryVisitor.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/OracleSelectQueryVisitor.java @@ -25,6 +25,8 @@ import it.eng.spagobi.tools.dataset.common.datawriter.CockpitJSONDataWriter; import it.eng.spagobi.tools.dataset.common.query.AggregationFunctions; import it.eng.spagobi.tools.dataset.common.query.IAggregationFunction; +import it.eng.spagobi.tools.dataset.metasql.query.item.AbstractSelectionField; +import it.eng.spagobi.tools.dataset.metasql.query.item.DataStoreCalculatedField; import it.eng.spagobi.tools.dataset.metasql.query.item.InFilter; import it.eng.spagobi.tools.dataset.metasql.query.item.Projection; import it.eng.spagobi.tools.dataset.metasql.query.item.Sorting; @@ -32,7 +34,7 @@ public class OracleSelectQueryVisitor extends AbstractSelectQueryVisitor { - private static final int SQL_IN_CLAUSE_LIMIT = 999; + private static int SQL_IN_CLAUSE_LIMIT = 999; private static final String DATE_FORMAT = "YYYY-MM-DD HH24:MI:SS"; private static final String TIMESTAMP_FORMAT = DATE_FORMAT + ".FF"; @@ -42,6 +44,7 @@ public OracleSelectQueryVisitor(IDataBase database) { @Override protected void append(InFilter item) { + queryBuilder.append(" ("); List projections = item.getProjections(); String openBracket; if (projections.size() > 1) { @@ -64,28 +67,133 @@ protected void append(InFilter item) { } queryBuilder.append(closeBracket); + List operands = item.getOperands(); - queryBuilder.append(" "); - queryBuilder.append(item.getOperator()); - queryBuilder.append(" ("); + if (operands.size() < SQL_IN_CLAUSE_LIMIT) { - List operands = item.getOperands(); - for (int i = 0; i < operands.size(); i++) { - if (i % projections.size() == 0) { // 1st item of tuple of values - if (i >= projections.size()) { // starting from 2nd tuple of values + queryBuilder.append(" "); + queryBuilder.append(item.getOperator()); + queryBuilder.append(" ("); + + for (int i = 0; i < operands.size(); i++) { + if (i % projections.size() == 0) { // 1st item of tuple of values + if (i >= projections.size()) { // starting from 2nd tuple of values + queryBuilder.append(","); + } + queryBuilder.append(openBracket); + } + if (i % projections.size() != 0) { queryBuilder.append(","); } - queryBuilder.append(openBracket); - } - if (i % projections.size() != 0) { - queryBuilder.append(","); + append(operands.get(i)); + if (i % projections.size() == projections.size() - 1) { // last item of tuple of values + queryBuilder.append(closeBracket); + } } - append(operands.get(i)); - if (i % projections.size() == projections.size() - 1) { // last item of tuple of values - queryBuilder.append(closeBracket); + queryBuilder.append(")"); + } else { + if (projections.size() == 1) { + int temp = 0; + for (int i = 0; i < operands.size(); i++) { + if (temp == 0 && i == 0) { + queryBuilder.append(" "); + queryBuilder.append(item.getOperator()); + queryBuilder.append(" ("); + + } else if (temp == 0 && i != 0) { + + queryBuilder.append(" OR "); + append(projections.get(0), false); + queryBuilder.append(" "); + queryBuilder.append(item.getOperator()); + queryBuilder.append(" ("); + + } + + if (i % projections.size() == 0 && temp != 0) { // 1st item of tuple of values + if (i >= projections.size()) { // starting from 2nd tuple of values + queryBuilder.append(","); + } + queryBuilder.append(openBracket); + } + if (i % projections.size() != 0) { + queryBuilder.append(","); + } + append(operands.get(i)); + if (i % projections.size() == projections.size() - 1) { // last item of tuple of values + queryBuilder.append(closeBracket); + } + temp++; + + if (temp == SQL_IN_CLAUSE_LIMIT) { + temp = 0; + queryBuilder.append(") "); + } + + } + String queryTemp = queryBuilder.toString().trim(); + if (!queryTemp.isEmpty() && !queryTemp.substring(queryTemp.length() - 1).equals(")")) + queryBuilder.append(")"); + } else { + + int temp = 0; + if (SQL_IN_CLAUSE_LIMIT % projections.size() != 0) { + SQL_IN_CLAUSE_LIMIT = SQL_IN_CLAUSE_LIMIT - 1; + } + for (int i = 0; i < operands.size(); i++) { + if (temp == 0 && i == 0) { + queryBuilder.append(" "); + queryBuilder.append(item.getOperator()); + queryBuilder.append(" ( ("); + + } else if (temp == 0 && i != 0) { + + queryBuilder.append(" OR "); + queryBuilder.append(" ("); + append(projections.get(0), false); + for (int ii = 1; ii < projections.size(); ii++) { + queryBuilder.append(","); + append(projections.get(ii), false); + } + queryBuilder.append(" )"); + queryBuilder.append(" "); + queryBuilder.append(item.getOperator()); + queryBuilder.append(" (("); + + } + + if (i % projections.size() == 0 && temp != 0) { // 1st item of tuple of values + if (i >= projections.size()) { // starting from 2nd tuple of values + queryBuilder.append(","); + } + queryBuilder.append(openBracket); + } + if (i % projections.size() != 0 && !(i != 0 && temp == 0)) { + queryBuilder.append(","); + } + append(operands.get(i)); + if (i % projections.size() == projections.size() - 1) { // last item of tuple of values + queryBuilder.append(closeBracket); + } + temp++; + + if (temp == SQL_IN_CLAUSE_LIMIT) { + temp = 0; + queryBuilder.append(") "); + } + + } + String queryTemp = queryBuilder.toString().trim(); + queryTemp = queryTemp.replaceAll("TO_TIMESTAMP\\([^)]+\\)", ""); + queryTemp = queryTemp.replaceAll("TO_DATE\\([^)]+\\)", ""); + + if (!queryTemp.isEmpty() + && !(queryTemp.substring(queryTemp.length() - 1).equals(")") && queryTemp.substring(queryTemp.length() - 2).equals("))"))) + queryBuilder.append(")"); + } - } + } queryBuilder.append(")"); } @@ -142,22 +250,47 @@ public String getFormattedDate(Date date) { @Override protected void append(Sorting item) { String aliasDelimiter = database.getAliasDelimiter(); - Projection projection = item.getProjection(); - IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + AbstractSelectionField proj = item.getProjection(); + + if (proj instanceof Projection) { - String name = aliasDelimiter + projection.getName() + aliasDelimiter; - if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { - queryBuilder.append(name); + Projection projection = (Projection) proj; + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + + String name = aliasDelimiter + projection.getName() + aliasDelimiter; + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(name); + } else { + String alias = projection.getAlias(); + if (alias != null && name.equals(aliasDelimiter + alias + aliasDelimiter)) { + queryBuilder.append(aliasDelimiter + alias + aliasDelimiter); + } else { + queryBuilder.append(aggregationFunction.apply(name)); + } + } + + queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); } else { - String alias = projection.getAlias(); - if (alias != null && name.equals(aliasDelimiter + alias + aliasDelimiter)) { - queryBuilder.append(aliasDelimiter + alias + aliasDelimiter); + + DataStoreCalculatedField projection = (DataStoreCalculatedField) proj; + IAggregationFunction aggregationFunction = projection.getAggregationFunction(); + + String name = aliasDelimiter + projection.getAlias() + aliasDelimiter; + if (aggregationFunction == null || AggregationFunctions.NONE_FUNCTION.equals(aggregationFunction)) { + queryBuilder.append(name); } else { - queryBuilder.append(aggregationFunction.apply(name)); + String alias = projection.getAlias(); + if (alias != null && name.equals(aliasDelimiter + alias + aliasDelimiter)) { + queryBuilder.append(aliasDelimiter + alias + aliasDelimiter); + } else { + queryBuilder.append(aggregationFunction.apply(name)); + } } + + queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); + } - queryBuilder.append(item.isAscending() ? " ASC" : " DESC"); } } diff --git a/knowage/src/main/webapp/themes/geobi/css/printImage.css b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/RedShiftSelectQueryVisitor.java similarity index 64% rename from knowage/src/main/webapp/themes/geobi/css/printImage.css rename to knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/RedShiftSelectQueryVisitor.java index 6b3453ddbe3..352dd93af3e 100644 --- a/knowage/src/main/webapp/themes/geobi/css/printImage.css +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/RedShiftSelectQueryVisitor.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,17 +11,19 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - */ - -/* CSS to print an image of dashboard*/ -#spagoBiHeader{display:none;} -.UITabs{display: none;} -.default-decorator{display: none;} -.community-toolbar-container{display: none;} -.portlet-info-bar{display: none;} -#changepars{display: none;} -#sliderform{display: none;} -#image{display: block; min-height: 200px; height: auto !important; height: 200px; min-width: 200px; width: auto !important; width: 200px;} + */ + +package it.eng.spagobi.tools.dataset.metasql.query.visitor; + +import it.eng.spagobi.utilities.database.IDataBase; + +public class RedShiftSelectQueryVisitor extends AbstractSelectQueryVisitor { + + public RedShiftSelectQueryVisitor(IDataBase database) { + super(database); + } + +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/SelectQueryVisitorFactory.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/SelectQueryVisitorFactory.java index 78324dfea1a..3a4bdc46aba 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/SelectQueryVisitorFactory.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/metasql/query/visitor/SelectQueryVisitorFactory.java @@ -53,6 +53,8 @@ public static ISelectQueryVisitor getVisitor(IDataSource dataSource) throws Data return new OrientDbSelectQueryVisitor(database); case TERADATA: return new TeradataSelectQueryVisitor(database); + case REDSHIFT: + return new RedShiftSelectQueryVisitor(database); default: throw new IllegalArgumentException("Dialect [" + dataSource.getHibDialectClass() + "] not supported"); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/ExtendedSolrQuery.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/ExtendedSolrQuery.java index 73cbe9528d2..1280d0b031a 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/ExtendedSolrQuery.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/ExtendedSolrQuery.java @@ -35,6 +35,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.tools.dataset.bo.IDataSet; import it.eng.spagobi.tools.dataset.common.query.AggregationFunctions; import it.eng.spagobi.tools.dataset.common.query.IAggregationFunction; @@ -52,15 +53,27 @@ public class ExtendedSolrQuery extends SolrQuery { private static final Logger logger = Logger.getLogger(ExtendedSolrQuery.class); + private int facetLimit = -1; + public ExtendedSolrQuery(SolrQuery initialQuery) { - if (initialQuery.getQuery() != null) + if (initialQuery.getQuery() != null) { setQuery(initialQuery.getQuery()); - if (initialQuery.getFilterQueries() != null) + } + if (initialQuery.getFilterQueries() != null) { setFilterQueries(initialQuery.getFilterQueries()); - if (initialQuery.getFields() != null) + } + if (initialQuery.getFields() != null) { setFields(initialQuery.getFields()); - if (initialQuery.getSorts() != null) + } + if (initialQuery.getSorts() != null) { setSorts(initialQuery.getSorts()); + } + + String facetLimitStr = SingletonConfig.getInstance().getConfigValue("SPAGOBI.DATASET.SOLR.FACET_LIMIT"); + if (facetLimitStr != null) { + facetLimit = Integer.valueOf(facetLimitStr); + } + logger.debug("Limiting the number of buckets for facet query to " + facetLimitStr + " buckets"); } public ExtendedSolrQuery filter(Filter filter) { @@ -193,7 +206,7 @@ private JSONObject getMeasureFacet(List measures) throws Projection pr = (Projection) measure; IAggregationFunction aggregationFunction = pr.getAggregationFunction(); - String key = FACET_PIVOT_MEASURE_ALIAS_PREFIX + pr.getName(); + String key = FACET_PIVOT_MEASURE_ALIAS_PREFIX + pr.getAliasOrName(); if (AggregationFunctions.COUNT.equals(aggregationFunction.getName())) { JSONObject value = new JSONObject(); value.put("type", "query"); @@ -209,7 +222,7 @@ private JSONObject getMeasureFacet(List measures) throws DataStoreCalculatedField pr = (DataStoreCalculatedField) measure; IAggregationFunction aggregationFunction = pr.getAggregationFunction(); - String key = FACET_PIVOT_MEASURE_ALIAS_PREFIX + pr.getName(); + String key = FACET_PIVOT_MEASURE_ALIAS_PREFIX + pr.getAliasOrName(); if (AggregationFunctions.COUNT.equals(aggregationFunction.getName())) { JSONObject value = new JSONObject(); value.put("type", "query"); @@ -261,17 +274,17 @@ private JSONObject getJsonFacet(AbstractSelectionField projection, JSONObject js String field = ""; if (projection instanceof Projection) { Projection proj = (Projection) projection; - fieldFacets = proj.getName(); + fieldFacets = proj.getAliasOrName(); field = proj.getName(); } else { DataStoreCalculatedField proj = (DataStoreCalculatedField) projection; - fieldFacets = proj.getName(); + fieldFacets = proj.getAliasOrName(); field = proj.getName(); } JSONObject innerFacet = new JSONObject(); innerFacet.put("type", "terms"); innerFacet.put("field", field); - innerFacet.put("limit", 10); + innerFacet.put("limit", facetLimit); innerFacet.put("missing", true); if (jsonFacet.length() > 0) { innerFacet.put("facet", jsonFacet); @@ -283,11 +296,22 @@ private JSONObject getJsonFacet(AbstractSelectionField projection, JSONObject js } private JSONObject getJsonFacet(Sorting sorting, JSONObject jsonFacet) throws JSONException { - Projection projection = sorting.getProjection(); - JSONObject outerFacet = getJsonFacet(projection, jsonFacet); - JSONObject innerFacet = outerFacet.getJSONObject(projection.getName() + FACET_PIVOT_CATEGORY_ALIAS_POSTFIX); - innerFacet.put("sort", "index " + (sorting.isAscending() ? "asc" : "desc")); - return outerFacet; + + AbstractSelectionField projs = sorting.getProjection(); + + if (projs instanceof Projection) { + Projection projection = (Projection) projs; + JSONObject outerFacet = getJsonFacet(projection, jsonFacet); + JSONObject innerFacet = outerFacet.getJSONObject(projection.getAliasOrName() + FACET_PIVOT_CATEGORY_ALIAS_POSTFIX); + innerFacet.put("sort", "index " + (sorting.isAscending() ? "asc" : "desc")); + return outerFacet; + } else { + DataStoreCalculatedField projection = (DataStoreCalculatedField) projs; + JSONObject outerFacet = getJsonFacet(projection, jsonFacet); + JSONObject innerFacet = outerFacet.getJSONObject(projection.getAliasOrName() + FACET_PIVOT_CATEGORY_ALIAS_POSTFIX); + innerFacet.put("sort", "index " + (sorting.isAscending() ? "asc" : "desc")); + return outerFacet; + } } public ExtendedSolrQuery facets(List groups) { diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrConfiguration.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrConfiguration.java index e6b7fba7672..1fb25bb0c59 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrConfiguration.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrConfiguration.java @@ -22,59 +22,74 @@ public class SolrConfiguration { - private String url; - private String collection; - private SolrQuery solrQuery; - private String solrFields; - private static final String WRITER_TYPE = "json"; //wt - private static final String DEFAULT_REQUEST_HANDLER = "select"; - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - if(!url.endsWith("/")) - url += "/"; - this.url = url; - } - - public String getCollection() { - return collection; - } - - public void setCollection(String collection) { - this.collection = collection; - } - - public SolrQuery getSolrQuery() { - return solrQuery; - } - - public void setSolrQuery(SolrQuery solrQuery) { - this.solrQuery = solrQuery; - } - - public String getSolrFields() { - return solrFields; - } - - public void setSolrFields(String solrFields) { - this.solrFields = solrFields; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(url); - if(!url.endsWith("/")) sb.append("/"); - sb.append(collection); - sb.append("/"); - sb.append(DEFAULT_REQUEST_HANDLER); - sb.append("?"); - sb.append(solrQuery); - sb.append("&"); - sb.append("wt=" + WRITER_TYPE); - return sb.toString(); - } + private String url; + private String collection; + private SolrQuery solrQuery; + private String solrFields; + private static final String WRITER_TYPE = "json"; // wt + private static final String DEFAULT_REQUEST_HANDLER = "select"; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + if (!url.endsWith("/")) + url += "/"; + this.url = url; + } + + public String getCollection() { + return collection; + } + + public void setCollection(String collection) { + this.collection = collection; + } + + public String getQueryParameters() { + StringBuilder sb = new StringBuilder(); + sb.append(solrQuery); + sb.append("&"); + sb.append("wt=" + WRITER_TYPE); + return sb.toString(); + } + + public SolrQuery getSolrQuery() { + return solrQuery; + } + + public void setSolrQuery(SolrQuery solrQuery) { + this.solrQuery = solrQuery; + } + + public String getSolrFields() { + return solrFields; + } + + public void setSolrFields(String solrFields) { + this.solrFields = solrFields; + } + + @Override + public String toString() { + return toString(true); + } + + public String toString(boolean withParameters) { + StringBuilder sb = new StringBuilder(); + sb.append(url); + if (!url.endsWith("/")) { + sb.append("/"); + } + sb.append(collection); + sb.append("/"); + sb.append(DEFAULT_REQUEST_HANDLER); + if (withParameters) { + sb.append("?"); + sb.append(getQueryParameters()); + } + return sb.toString(); + } + } diff --git a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrDataStore.java b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrDataStore.java index 9888df26f83..ca678945b48 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrDataStore.java +++ b/knowageutils/src/main/java/it/eng/spagobi/tools/dataset/solr/SolrDataStore.java @@ -19,33 +19,39 @@ package it.eng.spagobi.tools.dataset.solr; -import it.eng.spagobi.tools.dataset.common.datastore.DataStore; -import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import org.apache.log4j.Logger; - import java.util.HashMap; import java.util.Map; +import org.apache.log4j.Logger; + +import it.eng.spagobi.tools.dataset.common.datastore.DataStore; +import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; + public class SolrDataStore extends DataStore { - private static final Logger logger = Logger.getLogger(SolrDataStore.class); - - private Map facets = new HashMap<>(); + private static final Logger logger = Logger.getLogger(SolrDataStore.class); + + private Map facets = new HashMap<>(); + + public SolrDataStore(IDataStore documentDataStore) { + records = documentDataStore.getRecords(); + metaData = documentDataStore.getMetaData(); + } - public SolrDataStore(IDataStore documentDataStore) { - records = documentDataStore.getRecords(); - metaData = documentDataStore.getMetaData(); - } + public SolrDataStore(Map facets) { + super(); + this.facets = facets; + } - public Map getFacets() { - return facets; - } + public Map getFacets() { + return facets; + } - public void setFacets(Map facets) { - this.facets = facets; - } + public void setFacets(Map facets) { + this.facets = facets; + } - public void addFacetDataStore(String name, IDataStore dataStore) { - facets.put(name, dataStore); - } + public void addFacetDataStore(String name, IDataStore dataStore) { + facets.put(name, dataStore); + } } diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/CacheInterface.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/CacheInterface.java index a871a219060..b66956df69b 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/CacheInterface.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/CacheInterface.java @@ -33,4 +33,6 @@ public interface CacheInterface { Serializable get(String code); boolean contains(String code); + + void clear(); } diff --git a/knowage/src/main/webapp/themes/geobi/css/commons/common.css b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/ConfigurationCache.java similarity index 74% rename from knowage/src/main/webapp/themes/geobi/css/commons/common.css rename to knowageutils/src/main/java/it/eng/spagobi/utilities/cache/ConfigurationCache.java index 5337868f60b..63193311eb7 100644 --- a/knowage/src/main/webapp/themes/geobi/css/commons/common.css +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/ConfigurationCache.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,12 +11,17 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . - */ - -.x-livesearch-match { - font-weight: bold; - background-color: yellow; -} \ No newline at end of file + */ +package it.eng.spagobi.utilities.cache; + +public class ConfigurationCache { + + public static CacheInterface getCache() { + GenericCacheFactory genericCacheFactory = new GenericCacheFactory(); + return genericCacheFactory.getCache("configuration"); + } + +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericCacheFactory.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericCacheFactory.java index e66d900994b..c126b09bb90 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericCacheFactory.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericCacheFactory.java @@ -19,7 +19,7 @@ /** * A factory for cache objects implementing the CacheInterface - * + * * @author Marco Cortella (marco.cortella@eng.it) * */ @@ -29,7 +29,7 @@ public class GenericCacheFactory { * @return a specific cache with the passed cache name */ public CacheInterface getCache(String cacheName) { - CacheInterface cache = GenericEhCacheImpl.getInstance(cacheName); + CacheInterface cache = new GenericEhCacheImpl(cacheName); return cache; } diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericEhCacheImpl.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericEhCacheImpl.java index 56f7570f465..e7ffb8680e4 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericEhCacheImpl.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/cache/GenericEhCacheImpl.java @@ -17,15 +17,17 @@ */ package it.eng.spagobi.utilities.cache; +import java.io.IOException; import java.io.Serializable; +import org.apache.log4j.Logger; + +import it.eng.spagobi.utilities.exceptions.SpagoBIRuntimeException; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheException; import net.sf.ehcache.CacheManager; import net.sf.ehcache.Element; -import org.apache.log4j.Logger; - /** * Implementation of the cache that uses the EhCache library (http://www.ehcache.org/) * @@ -37,30 +39,28 @@ public class GenericEhCacheImpl implements CacheInterface { private static transient Logger logger = Logger.getLogger(GenericEhCacheImpl.class); - private static GenericEhCacheImpl instance; - private Cache cache = null; - private CacheManager manager; + private static CacheManager manager; - public GenericEhCacheImpl(String cacheName) { - super(); + static { try { manager = CacheManager.create(); - cache = manager.getCache(cacheName); - } catch (CacheException e) { - logger.error("CacheException in inizialization", e); + } catch (Exception e) { + logger.error("Error while initialization CacheManager instance", e); } - } - public synchronized static CacheInterface getInstance(String cacheName) { - if (instance == null) { - logger.debug("Creating cache for[" + cacheName + "]"); - instance = new GenericEhCacheImpl(cacheName); + public GenericEhCacheImpl(String cacheName) { + super(); + try { + if (manager == null) { + throw new SpagoBIRuntimeException("Cache manager was not initialized properly"); + } + cache = manager.getCache(cacheName); + } catch (Exception e) { + logger.error("Exception when inizializating cache", e); } - logger.debug("Cache for[" + cacheName + "] already found"); - return instance; } @Override @@ -101,7 +101,7 @@ public Serializable get(String code) { try { Element el = cache.get(code); logger.debug("Retrieving element with code [" + code + "] from the cache"); - return el.getValue(); + return el != null ? el.getValue() : null; } catch (IllegalStateException e) { logger.error("IllegalStateException", e); } catch (CacheException e) { @@ -110,4 +110,16 @@ public Serializable get(String code) { } return null; } + + @Override + public void clear() { + if (cache != null) { + try { + cache.removeAll(); + } catch (IllegalStateException | IOException e) { + logger.error("An error occurred while clearing cache", e); + } + } + } + } diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/database/DataBaseFactory.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/database/DataBaseFactory.java index 794185e3c10..f24435afa0d 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/database/DataBaseFactory.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/database/DataBaseFactory.java @@ -73,6 +73,8 @@ public static IDataBase getDataBase(IDataSource dataSource) throws DataBaseExcep return new MongoDataBase(dataSource); case VERTICA: return new VerticaDataBase(dataSource); + case REDSHIFT: + return new RedShiftDataBase(dataSource); default: throw new DataBaseException("Impossible to find a database implementation for [" + sqlDialect.toString() + "]"); } diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/database/RedShiftDataBase.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/database/RedShiftDataBase.java new file mode 100644 index 00000000000..6666c2b43d1 --- /dev/null +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/database/RedShiftDataBase.java @@ -0,0 +1,114 @@ +/* + * Knowage, Open Source Business Intelligence suite + * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. + * + * Knowage is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Knowage 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package it.eng.spagobi.utilities.database; + +import org.apache.log4j.Logger; + +import it.eng.spagobi.tools.datasource.bo.IDataSource; + +public class RedShiftDataBase extends AbstractDataBase implements CacheDataBase { + + private static transient Logger logger = Logger.getLogger(PostgreSQLDataBase.class); + + private static int MAX_VARCHAR_VALUE = 10485760; + + private int varcharLength = 255; + + public RedShiftDataBase(IDataSource dataSource) { + super(dataSource); + } + + @Override + public int getVarcharLength() { + return varcharLength; + } + + @Override + public void setVarcharLength(int varcharLength) { + this.varcharLength = varcharLength; + } + + @Override + public String getDataBaseType(Class javaType) { + String toReturn = null; + String javaTypeName = javaType.toString(); + if (javaTypeName.contains("java.lang.String") && getVarcharLength() <= MAX_VARCHAR_VALUE) { + toReturn = " VARCHAR (" + getVarcharLength() + ")"; + } else if (javaTypeName.contains("java.lang.Byte")) { + toReturn = " INTEGER "; + } else if (javaTypeName.contains("java.lang.Short")) { + toReturn = " INTEGER "; + } else if (javaTypeName.contains("java.lang.Integer")) { + toReturn = " INTEGER "; + } else if (javaTypeName.contains("java.lang.Long")) { + toReturn = " NUMERIC "; + } else if (javaTypeName.contains("java.lang.BigDecimal") || javaTypeName.contains("java.math.BigDecimal")) { + toReturn = " NUMERIC "; + } else if (javaTypeName.contains("java.lang.Double")) { + toReturn = " NUMERIC "; + } else if (javaTypeName.contains("java.lang.Float")) { + toReturn = " NUMERIC "; + } else if (javaTypeName.contains("java.lang.Boolean")) { + toReturn = " BOOLEAN "; + } else if (javaTypeName.contains("java.sql.Date") || javaTypeName.contains("java.util.Date")) { + toReturn = " DATE "; + } else if (javaTypeName.toLowerCase().contains("timestamp")) { + toReturn = " TIMESTAMP "; + } else if (javaTypeName.contains("java.sql.Time")) { + toReturn = " TIME "; + } else if (javaTypeName.contains("[B") || javaTypeName.contains("BLOB")) { + toReturn = " BYTEA "; + } else if ((javaTypeName.contains("java.lang.String") && getVarcharLength() > MAX_VARCHAR_VALUE) || javaTypeName.contains("[C") + || javaTypeName.contains("CLOB") || javaTypeName.contains("JSON") || javaTypeName.contains("Map") || javaTypeName.contains("List")) { + toReturn = " TEXT "; + } else { + toReturn = " TEXT "; + logger.error("Cannot map java type [" + javaTypeName + "] to a valid database type. Set TEXT by default "); + } + + return toReturn; + } + + /* + * (non-Javadoc) + * + * @see it.eng.spagobi.utilities.database.IDataBase#getAliasDelimiter() + */ + @Override + public String getAliasDelimiter() { + return "\""; + } + + /* + * (non-Javadoc) + * + * @see it.eng.spagobi.utilities.database.AbstractDataBase#getUsedMemorySizeQuery(java.lang.String, java.lang.String) + */ + @Override + public String getUsedMemorySizeQuery(String schema, String tableNamePrefix) { + String query = " SELECT " + " CASE count(*) " + " WHEN 0 THEN 0 " + + " ELSE SUM(pg_total_relation_size('\"' || table_schema || '\".\"' || table_name || '\"')) " + " END AS size " + + " FROM information_schema.tables " + " WHERE " + " table_name like '" + tableNamePrefix + "%'"; + if ((schema != null) && (!schema.isEmpty())) { + query += " AND table_schema = '" + schema + "'"; + } + return query; + } + +} diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/rest/RestUtilities.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/rest/RestUtilities.java index 3e0ea421c22..a5b9430cdcb 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/rest/RestUtilities.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/rest/RestUtilities.java @@ -61,6 +61,7 @@ import org.json.JSONException; import org.json.JSONObject; +import it.eng.spagobi.commons.SingletonConfig; import it.eng.spagobi.commons.utilities.SpagoBIUtilities; import it.eng.spagobi.commons.utilities.StringUtilities; import it.eng.spagobi.security.hmacfilter.HMACFilterAuthenticationProvider; @@ -83,10 +84,6 @@ public class RestUtilities { private static final String HTTP_TIMEOUT_PROPERTY = "http.timeout"; private static final int HTTP_TIMEOUT_DEFAULT_VALUE = 30 * 1000; - static { - loadHttpTimeout(); - } - private static void loadHttpTimeout() { timeout = HTTP_TIMEOUT_DEFAULT_VALUE; @@ -102,6 +99,12 @@ private static void loadHttpTimeout() { logger.error("Unable to set HTTP timeout to value [" + timeoutProp + "]. It must be a number.", e); } } + String timeoutStr = SingletonConfig.getInstance().getConfigValue("SPAGOBI.DATASET.REST.TIMEOUT"); + if (timeoutStr != null) { + timeout = Integer.valueOf(timeoutStr); + logger.debug("The SPAGOBI.DATASET.REST.TIMEOUT configuration overwrire the timeout with the value " + timeout); + } + } /** @@ -122,15 +125,6 @@ public static void setProxyPort(int proxyPort) { RestUtilities.proxyPort = proxyPort; } - /** - * For testing purpose - * - * @param timeout - */ - public static void setTimeout(int timeout) { - RestUtilities.timeout = timeout; - } - /** * @deprecated This function could give problem with XSS.
* Inplace of this, please use one of
@@ -400,6 +394,7 @@ public void close() throws IOException { protected static HttpClient getHttpClient(String address) { HttpClient client = new HttpClient(); + loadHttpTimeout(); client.setTimeout(timeout); setHttpClientProxy(client, address); return client; diff --git a/knowageutils/src/main/java/it/eng/spagobi/utilities/service/AbstractBaseHttpAction.java b/knowageutils/src/main/java/it/eng/spagobi/utilities/service/AbstractBaseHttpAction.java index d90618f345b..b61f21dfb18 100644 --- a/knowageutils/src/main/java/it/eng/spagobi/utilities/service/AbstractBaseHttpAction.java +++ b/knowageutils/src/main/java/it/eng/spagobi/utilities/service/AbstractBaseHttpAction.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,21 +11,12 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.spagobi.utilities.service; -import it.eng.spago.base.SessionContainer; -import it.eng.spago.base.SourceBean; -import it.eng.spago.dispatching.action.AbstractHttpAction; -import it.eng.spagobi.container.IBeanContainer; -import it.eng.spagobi.container.SpagoBIHttpSessionContainer; -import it.eng.spagobi.container.SpagoBIRequestContainer; -import it.eng.spagobi.container.SpagoBIResponseContainer; -import it.eng.spagobi.container.SpagoBISessionContainer; - import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.File; @@ -44,154 +35,161 @@ import org.json.JSONArray; import org.json.JSONObject; +import it.eng.spago.base.SessionContainer; +import it.eng.spago.base.SourceBean; +import it.eng.spago.dispatching.action.AbstractHttpAction; +import it.eng.spago.security.IEngUserProfile; +import it.eng.spagobi.commons.bo.UserProfile; +import it.eng.spagobi.container.IBeanContainer; +import it.eng.spagobi.container.SpagoBIHttpSessionContainer; +import it.eng.spagobi.container.SpagoBIRequestContainer; +import it.eng.spagobi.container.SpagoBIResponseContainer; +import it.eng.spagobi.container.SpagoBISessionContainer; /** * @author Andrea Gioia (andrea.gioia@eng.it) * */ public abstract class AbstractBaseHttpAction extends AbstractHttpAction { - + private SpagoBIRequestContainer spagoBIRequestContainer; private SpagoBIResponseContainer spagoBIResponseContainer; private SpagoBISessionContainer spagoBISessionContainer; private SpagoBIHttpSessionContainer spagoHttpBISessionContainer; - - + /** - * Logger component - */ - private static transient Logger logger = Logger.getLogger(AbstractBaseHttpAction.class); - - + * Logger component + */ + private static transient Logger logger = Logger.getLogger(AbstractBaseHttpAction.class); + + @Override public void init(SourceBean config) { - super.init(config); - } - + super.init(config); + } // ================================================================================================= - // REQUEST utility methods + // REQUEST utility methods // ================================================================================================= - - + protected SpagoBIRequestContainer getSpagoBIRequestContainer() { return spagoBIRequestContainer; - + } protected void setSpagoBIRequestContainer(SourceBean request) { - spagoBIRequestContainer = new SpagoBIRequestContainer( request ); + spagoBIRequestContainer = new SpagoBIRequestContainer(request); } - - public boolean requestContainsAttribute(String attrName) { - return !getSpagoBIRequestContainer().isNull( attrName ); + + public boolean requestContainsAttribute(String attrName) { + return !getSpagoBIRequestContainer().isNull(attrName); } - + public boolean requestContainsAttribute(String attrName, String attrValue) { - return ( requestContainsAttribute(attrName) && getAttribute(attrName).toString().equalsIgnoreCase(attrValue) ); + return (requestContainsAttribute(attrName) && getAttribute(attrName).toString().equalsIgnoreCase(attrValue)); } - + public Object getAttribute(String attrName) { return getSpagoBIRequestContainer().get(attrName); } - + public String getAttributeAsString(String attrName) { - return getSpagoBIRequestContainer().getString( attrName ); + return getSpagoBIRequestContainer().getString(attrName); } - + public Integer getAttributeAsInteger(String attrName) { - return getSpagoBIRequestContainer().getInteger( attrName ); + return getSpagoBIRequestContainer().getInteger(attrName); } - + public boolean getAttributeAsBoolean(String attrName) { return getAttributeAsBoolean(attrName, false); } public boolean getAttributeAsBoolean(String attrName, boolean defaultValue) { - if( getAttribute(attrName) == null ) return defaultValue; - return getSpagoBIRequestContainer().getBoolean( attrName ).booleanValue(); + if (getAttribute(attrName) == null) + return defaultValue; + return getSpagoBIRequestContainer().getBoolean(attrName).booleanValue(); } - + public List getAttributeAsList(String attrName) { - return getSpagoBIRequestContainer().toList( attrName ); + return getSpagoBIRequestContainer().toList(attrName); } - + public List getAttributeAsCsvStringList(String attrName, String separator) { - return getSpagoBIRequestContainer().toCsvList( attrName ); + return getSpagoBIRequestContainer().toCsvList(attrName); } - + public JSONObject getAttributeAsJSONObject(String attrName) { - return getSpagoBIRequestContainer().toJSONObject( attrName ); - } - + return getSpagoBIRequestContainer().toJSONObject(attrName); + } + public JSONArray getAttributeAsJSONArray(String attrName) { - return getSpagoBIRequestContainer().toJSONArray( attrName ); - } - - public Map getAttributesAsMap() { - + return getSpagoBIRequestContainer().toJSONArray(attrName); + } + + public Map getAttributesAsMap() { + List attributeNames; String attributeName; Object attributeVaue; - HashMap attributesMap; + HashMap attributesMap; Iterator it; - - attributesMap = new HashMap (); + + attributesMap = new HashMap(); attributeNames = getSpagoBIRequestContainer().getKeys(); - + it = attributeNames.iterator(); - while( it.hasNext() ) { - attributeName = (String)it.next(); + while (it.hasNext()) { + attributeName = (String) it.next(); attributeVaue = getAttribute(attributeName); attributesMap.put(attributeName, attributeVaue); } - + return attributesMap; } - -public LinkedHashMap getAttributesAsLinkedMap() { - + + public LinkedHashMap getAttributesAsLinkedMap() { + List attributeNames; String attributeName; Object attributeVaue; - LinkedHashMap attributesMap; + LinkedHashMap attributesMap; Iterator it; - - attributesMap = new LinkedHashMap (); + + attributesMap = new LinkedHashMap(); attributeNames = getSpagoBIRequestContainer().getKeys(); - + it = attributeNames.iterator(); - while( it.hasNext() ) { - attributeName = (String)it.next(); + while (it.hasNext()) { + attributeName = (String) it.next(); attributeVaue = getAttribute(attributeName); attributesMap.put(attributeName, attributeVaue); } - + return attributesMap; } - - + // ================================================================================================= // RESPONSE utility methods // ================================================================================================= - + protected SpagoBIResponseContainer getSpagoBIResponseContainer() { return this.spagoBIResponseContainer; } protected void setSpagoBIResponseContainer(SourceBean response) { - this.spagoBIResponseContainer = new SpagoBIResponseContainer( response ); + this.spagoBIResponseContainer = new SpagoBIResponseContainer(response); } - + /** * Sets the attribute. - * - * @param key the key + * + * @param key the key * @param value the value */ public void setAttribute(String key, Object value) { getSpagoBIResponseContainer().set(key, value); } - + public boolean tryToWriteBackToClient(String message) { try { writeBackToClient(message); @@ -199,33 +197,26 @@ public boolean tryToWriteBackToClient(String message) { logger.error("Impossible to write back to the client the message: [" + message + "]", e); return false; } - + return true; } - + public void writeBackToClient(String message) throws IOException { - writeBackToClient(200, message, - true, - "service-response", - "text/plain"); + writeBackToClient(200, message, true, "service-response", "text/plain"); } - + public void writeBackToClient(IServiceResponse response) throws IOException { - writeBackToClient(response.getStatusCode(), - response.getContent(), - response.isInline(), - response.getFileName(), - response.getContentType()); + writeBackToClient(response.getStatusCode(), response.getContent(), response.isInline(), response.getFileName(), response.getContentType()); } - + public void writeBackToClient(int statusCode, String content, boolean inline, String fileName, String contentType) throws IOException { freezeHttpResponse(); - + // setup response header if (fileName != null) { - getHttpResponse().setHeader("Content-Disposition", (inline?"inline":"attachment") + "; filename=\"" + fileName + "\";"); + getHttpResponse().setHeader("Content-Disposition", (inline ? "inline" : "attachment") + "; filename=\"" + fileName + "\";"); } - getHttpResponse().setContentType( contentType ); + getHttpResponse().setContentType(contentType); // encoding content using UTF8, since content length depends on encoding String utf8EncodedContent = null; if (content != null) { @@ -233,22 +224,21 @@ public void writeBackToClient(int statusCode, String content, boolean inline, St } else { utf8EncodedContent = ""; } - //getHttpResponse().setContentLength( utf8EncodedContent.length() ); - getHttpResponse().setCharacterEncoding( "UTF-8" ); + // getHttpResponse().setContentLength( utf8EncodedContent.length() ); + getHttpResponse().setCharacterEncoding("UTF-8"); getHttpResponse().setStatus(statusCode); - + getHttpResponse().getWriter().print(utf8EncodedContent); getHttpResponse().getWriter().flush(); } - - public void writeBackToClient(File file, IStreamEncoder encoder, - boolean inline, String contentName, String contentType) throws IOException { + + public void writeBackToClient(File file, IStreamEncoder encoder, boolean inline, String contentName, String contentType) throws IOException { FileInputStream fis = null; BufferedInputStream bis = null; - - logger.debug("Flushing file [" + file.getName() +"] - " + inline + " - " + contentType); + + logger.debug("Flushing file [" + file.getName() + "] - " + inline + " - " + contentType); try { - fis = new FileInputStream( file ); + fis = new FileInputStream(file); bis = new BufferedInputStream(fis); writeBackToClient(bis, encoder, inline, contentName, contentType); } finally { @@ -258,35 +248,34 @@ public void writeBackToClient(File file, IStreamEncoder encoder, if (fis != null) { fis.close(); } - } + } } - - public void writeBackToClient(InputStream in, IStreamEncoder encoder, boolean inline, String contentName, String contentType) throws IOException { + + public void writeBackToClient(InputStream in, IStreamEncoder encoder, boolean inline, String contentName, String contentType) throws IOException { int contentLength = 0; int b = -1; - + freezeHttpResponse(); - + // setup response header - getHttpResponse().setHeader("Content-Disposition", (inline?"inline":"attachment") + "; filename=\"" + contentName + "\";"); - getHttpResponse().setContentType( contentType ); - - if(encoder == null) { + getHttpResponse().setHeader("Content-Disposition", (inline ? "inline" : "attachment") + "; filename=\"" + contentName + "\";"); + getHttpResponse().setContentType(contentType); + + if (encoder == null) { byte[] buf = new byte[1024]; - while((b = in.read(buf)) != -1) { + while ((b = in.read(buf)) != -1) { getHttpResponse().getOutputStream().write(buf, 0, b); - contentLength+=b; - } - getHttpResponse().setContentLength( contentLength ); + contentLength += b; + } + getHttpResponse().setContentLength(contentLength); } else { encoder.encode(in, getHttpResponse().getOutputStream()); } getHttpResponse().getOutputStream().flush(); getHttpResponse().getOutputStream().close(); - - + } - + public void writeBackToClient(byte[] bytes, IStreamEncoder encoder, boolean inline, String contentName, String contentType) throws IOException { InputStream is = null; try { @@ -298,33 +287,33 @@ public void writeBackToClient(byte[] bytes, IStreamEncoder encoder, boolean inli } } } - + // ================================================================================================= // SESSION utility methods // ================================================================================================= - + public SessionContainer getSessionContainer() { return getRequestContainer().getSessionContainer(); } - + public IBeanContainer getSpagoBISessionContainer() { - if(spagoBISessionContainer == null) { - spagoBISessionContainer = new SpagoBISessionContainer( getSessionContainer() ); + if (spagoBISessionContainer == null) { + spagoBISessionContainer = new SpagoBISessionContainer(getSessionContainer()); } - + return spagoBISessionContainer; } - + public boolean sessionContainsAttribute(String attrName) { return !getSpagoBISessionContainer().isNull(attrName); } - + public Object getAttributeFromSession(String attrName) { - return getSpagoBISessionContainer().get( attrName ); + return getSpagoBISessionContainer().get(attrName); } public String getAttributeFromSessionAsString(String attrName) { - return getSpagoBISessionContainer().getString( attrName ); + return getSpagoBISessionContainer().getString(attrName); } public boolean getAttributeFromSessionAsBoolean(String attrName) { @@ -332,74 +321,76 @@ public boolean getAttributeFromSessionAsBoolean(String attrName) { } public boolean getAttributeFromSessionAsBoolean(String attrName, boolean defaultValue) { - if( !sessionContainsAttribute(attrName) ) return defaultValue; - return getSpagoBISessionContainer().getBoolean( attrName ).booleanValue(); + if (!sessionContainsAttribute(attrName)) + return defaultValue; + return getSpagoBISessionContainer().getBoolean(attrName).booleanValue(); } - + public void delAttributeFromSession(String attrName) { - if( sessionContainsAttribute(attrName) ) { + if (sessionContainsAttribute(attrName)) { getSpagoBISessionContainer().remove(attrName); } } - - + public void setAttributeInSession(String attrName, Object attrValue) { delAttributeFromSession(attrName); getSpagoBISessionContainer().set(attrName, attrValue); - } - - + } + // ================================================================================================= // HTTP-SESSION utility methods // ================================================================================================= - - - public HttpSession getHttpSession() { + + public HttpSession getHttpSession() { return getHttpRequest().getSession(); } - + public IBeanContainer getSpagoBIHttpSessionContainer() { - if(spagoHttpBISessionContainer == null) { - spagoHttpBISessionContainer = new SpagoBIHttpSessionContainer( getHttpSession() ); + if (spagoHttpBISessionContainer == null) { + spagoHttpBISessionContainer = new SpagoBIHttpSessionContainer(getHttpSession()); } - + return spagoHttpBISessionContainer; } - + public boolean httpSessionContainsAttribute(String attrName) { return !getSpagoBIHttpSessionContainer().isNull(attrName); } - - + public Object getAttributeFromHttpSession(String attrName) { return getSpagoBIHttpSessionContainer().get(attrName); } - - + public String getAttributeFromHttpSessionAsString(String attrName) { return getSpagoBIHttpSessionContainer().getString(attrName); } - - + public boolean getAttributeFromHttpSessionAsBoolean(String attrName) { return getAttributeFromHttpSessionAsBoolean(attrName, false); } - public boolean getAttributeFromHttpSessionAsBoolean(String attrName, boolean defaultValue) { - if( !httpSessionContainsAttribute(attrName) ) return defaultValue; - return getSpagoBIHttpSessionContainer().getBoolean( attrName ).booleanValue(); + if (!httpSessionContainsAttribute(attrName)) + return defaultValue; + return getSpagoBIHttpSessionContainer().getBoolean(attrName).booleanValue(); } - + public void delAttributeFromHttpSession(String attrName) { - if( httpSessionContainsAttribute(attrName) ) { + if (httpSessionContainsAttribute(attrName)) { getSpagoBIHttpSessionContainer().remove(attrName); } } - + public void setAttributeInHttpSession(String attrName, Object attrValue) { delAttributeFromHttpSession(attrName); getSpagoBIHttpSessionContainer().set(attrName, attrValue); - } + } + + protected void storeProfileInSession(UserProfile userProfile, SessionContainer permanentContainer, HttpSession httpSession) { + logger.debug("IN"); + permanentContainer.setAttribute(IEngUserProfile.ENG_USER_PROFILE, userProfile); + httpSession.setAttribute(IEngUserProfile.ENG_USER_PROFILE, userProfile); + logger.debug("OUT"); + } } diff --git a/knowageutils/src/main/resources/predefinedGroovyScript.groovy b/knowageutils/src/main/resources/predefinedGroovyScript.groovy index 55b49eea1d8..639a5c7849d 100644 --- a/knowageutils/src/main/resources/predefinedGroovyScript.groovy +++ b/knowageutils/src/main/resources/predefinedGroovyScript.groovy @@ -58,3 +58,7 @@ public String split(String attrName, String splitter) { strBuf.append(""); return strBuf.toString(); }; + +public String NULLIF(BigDecimal expression1, Integer expression2) { + return expression1.compareTo(expression2)==0 ? null : expression1; +}; \ No newline at end of file diff --git a/knowageutils/src/test/java/it/eng/spagobi/UtilitiesForTest.java b/knowageutils/src/test/java/it/eng/spagobi/UtilitiesForTest.java index 9b4d23fbbec..f77500108dc 100644 --- a/knowageutils/src/test/java/it/eng/spagobi/UtilitiesForTest.java +++ b/knowageutils/src/test/java/it/eng/spagobi/UtilitiesForTest.java @@ -17,14 +17,6 @@ */ package it.eng.spagobi; -import it.eng.spago.configuration.ConfigSingleton; -import it.eng.spago.configuration.FileCreatorConfiguration; -import it.eng.spagobi.commons.SimpleSingletonConfigCache; -import it.eng.spagobi.commons.SingletonConfig; -import it.eng.spagobi.utilities.MockContext; -import it.eng.spagobi.utilities.MockFactory; -import it.eng.spagobi.utilities.MockHttpSession; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -41,6 +33,14 @@ import org.apache.commons.io.FileUtils; import org.junit.Assert; +import it.eng.spago.configuration.ConfigSingleton; +import it.eng.spago.configuration.FileCreatorConfiguration; +import it.eng.spagobi.commons.SimpleConfigurationRetriever; +import it.eng.spagobi.commons.SingletonConfig; +import it.eng.spagobi.utilities.MockContext; +import it.eng.spagobi.utilities.MockFactory; +import it.eng.spagobi.utilities.MockHttpSession; + public class UtilitiesForTest { public static void setUpMasterConfiguration() { @@ -74,21 +74,21 @@ public static void setUpTestJNDI() throws Exception { ic.bind("java://comp/env/sso_class", "it.eng.spagobi.services.common.FakeSsoService"); ic.bind("java:/comp/env/jdbc/hdfs_url", "hdfs://192.168.56.1:8020"); - SimpleSingletonConfigCache cache = new SimpleSingletonConfigCache(); - cache.setProperty("SPAGOBI.ORGANIZATIONAL-UNIT.hdfsResource", "java:/comp/env/jdbc/hdfs_url"); - cache.setProperty("SPAGOBI_SSO.INTEGRATION_CLASS_JNDI", "java:/comp/env/sso_class"); - SingletonConfig.getInstance().setCache(cache); + SimpleConfigurationRetriever configuration = new SimpleConfigurationRetriever(); + configuration.setProperty("SPAGOBI.ORGANIZATIONAL-UNIT.hdfsResource", "java:/comp/env/jdbc/hdfs_url"); + configuration.setProperty("SPAGOBI_SSO.INTEGRATION_CLASS_JNDI", "java:/comp/env/sso_class"); + SingletonConfig.getInstance().setConfigurationRetriever(configuration); } public static void writeSessionOfWebApp() throws IOException, InterruptedException { Runtime runtime = Runtime.getRuntime(); // call login page of knowage to write JSESSION COOKIE - Process exec = runtime - .exec("curl http://localhost:8080/knowage/servlet/AdapterHTTP?PAGE=LoginPage&NEW_SESSION=TRUE -H 'Host: localhost:8080' -c ./resources-test/cookies.txt"); + Process exec = runtime.exec( + "curl http://localhost:8080/knowage/servlet/AdapterHTTP?PAGE=LoginPage&NEW_SESSION=TRUE -H 'Host: localhost:8080' -c ./resources-test/cookies.txt"); exec.waitFor(); String jsessionId = getJSessionId(); - exec = runtime - .exec("curl http://localhost:8080/knowage/servlet/AdapterHTTP?PAGE=LoginPage&NEW_SESSION=TRUE -H 'Host: localhost:8080' -H 'Cookie: JSESSIONID=%J' --data 'isInternalSecurity=true&userID=biadmin&password=biadmin'" + exec = runtime.exec( + "curl http://localhost:8080/knowage/servlet/AdapterHTTP?PAGE=LoginPage&NEW_SESSION=TRUE -H 'Host: localhost:8080' -H 'Cookie: JSESSIONID=%J' --data 'isInternalSecurity=true&userID=biadmin&password=biadmin'" .replace("%J", jsessionId)); exec.waitFor(); } diff --git a/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/bo/JDBCDataSetTest.java b/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/bo/JDBCDataSetTest.java index 9919c190c8a..cb3276cac78 100644 --- a/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/bo/JDBCDataSetTest.java +++ b/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/bo/JDBCDataSetTest.java @@ -17,15 +17,15 @@ */ package it.eng.spagobi.tools.dataset.bo; +import it.eng.spagobi.commons.bo.UserProfile; import it.eng.spagobi.services.dataset.bo.SpagoBiDataSet; +import it.eng.spagobi.services.datasource.bo.SpagoBiDataSource; import it.eng.spagobi.test.AbstractSpagoBITestCase; import it.eng.spagobi.test.TestDataSetFactory; import it.eng.spagobi.tools.dataset.common.datastore.IDataStore; -import it.eng.spagobi.tools.dataset.common.metadata.IFieldMetaData; -import it.eng.spagobi.tools.dataset.common.metadata.IMetaData; - -import java.util.HashMap; -import java.util.Map; +import it.eng.spagobi.tools.datasource.bo.JDBCDataSourcePoolConfiguration; +import it.eng.spagobi.tools.datasource.bo.serializer.JDBCDataSourcePoolConfigurationJSONSerializer; +import it.eng.spagobi.user.UserProfileManager; /** * @author Andrea Gioia (andrea.gioia@eng.it) @@ -39,12 +39,22 @@ public class JDBCDataSetTest extends AbstractSpagoBITestCase { public void setUp() throws Exception { super.setUp(); try { + UserProfileManager.setProfile(new UserProfile("biadmin", "DEFAULT_TENANT")); SpagoBiDataSet dataSetConfig = new SpagoBiDataSet(); - String conf = "{\"Query\":\"SELECT fullname as 'Full Name' FROM CUSTOMER LIMIT 10 \",\"queryScript\":\"\",\"queryScriptLanguage\":\"\",\"dataSource\":\"FoodMart\"}"; +// String conf = "{\"query\":\"SELECT fullname as 'Full Name' FROM CUSTOMER LIMIT 10 \",\"queryScript\":\"\",\"queryScriptLanguage\":\"\",\"dataSource\":\"foodmart\"}"; +// String conf = "{\"query\":\"SELECT catgroup FROM category LIMIT 10 \",\"queryScript\":\"\",\"queryScriptLanguage\":\"\",\"dataSource\":\"redshift_postgre\"}"; + String conf = "{\"query\":\"select d.YEAR,d.MONTH,d.WEEK,d.CALDATE,e.eventname, v.VENUESTATE,v.VENUECITY, qtysold, pricepaid,v.VENUESEATS\r\n" + + "from table_select s \r\n" + "inner join event e on e.eventid = s.eventid\r\n" + "inner join venue v on e.venueid = v.venueid\r\n" + + "inner join date d on e.dateid = d.dateid \",\"queryScript\":\"\",\"queryScriptLanguage\":\"\",\"dataSource\":\"redshift_postgre\"}"; + dataSetConfig.setConfiguration(conf); // dataSetConfig.setQuery("SELECT fullname as 'Full Name' FROM CUSTOMER LIMIT 10"); - dataSetConfig.setDataSource(TestDataSetFactory.createSpagoBiDataSource()); - dataset = new JDBCDataSet(); + + SpagoBiDataSource ds = TestDataSetFactory.createSpagoBiDataSource(); + ds.setJdbcPoolConfiguration((String) new JDBCDataSourcePoolConfigurationJSONSerializer().serialize(new JDBCDataSourcePoolConfiguration())); + dataSetConfig.setDataSource(ds); + dataset = new JDBCDataSet(dataSetConfig); + } catch (Exception t) { logger.error("An unespected error occurred during setUp: "); t.printStackTrace(); @@ -58,98 +68,99 @@ public void tearDown() throws Exception { } public void testDataSetLoad() { - dataset.loadData(); + dataset.setCalculateResultNumberOnLoad(false); + dataset.loadData(0, 10, 3000); IDataStore dataStore = dataset.getDataStore(); assertNotNull(dataStore); - assertEquals(10, dataStore.getRecordsCount()); - IMetaData metaData = dataStore.getMetaData(); - assertNotNull(metaData); - assertEquals(1, metaData.getFieldCount()); - IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); - assertEquals("Full Name", fieldMetaData.getName()); - assertEquals(null, fieldMetaData.getAlias()); - assertEquals(String.class, fieldMetaData.getType()); +// assertEquals(10, dataStore.getRecordsCount()); +// IMetaData metaData = dataStore.getMetaData(); +// assertNotNull(metaData); +// assertEquals(1, metaData.getFieldCount()); +// IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); +// assertEquals("Full Name", fieldMetaData.getName()); +// assertEquals(null, fieldMetaData.getAlias()); +// assertEquals(String.class, fieldMetaData.getType()); } - public void testSimpleScriptedQuery() { - String injectedStatement = "SELECT lname AS \\\'Last Name\\\' FROM CUSTOMER LIMIT 30"; - String script = "'" + injectedStatement + "';"; - dataset.setQueryScript(script); - dataset.setQueryScriptLanguage("ECMAScript"); - - dataset.loadData(); - IDataStore dataStore = dataset.getDataStore(); - assertNotNull(dataStore); - assertEquals(30, dataStore.getRecordsCount()); - IMetaData metaData = dataStore.getMetaData(); - assertNotNull(metaData); - assertEquals(1, metaData.getFieldCount()); - IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); - assertEquals("Last Name", fieldMetaData.getName()); - assertEquals(null, fieldMetaData.getAlias()); - assertEquals(String.class, fieldMetaData.getType()); - } - - public void testScriptedQueryTransform() { - String script = "query.replace(\"LIMIT 10\",\"LIMIT 30\");"; - dataset.setQueryScript(script); - dataset.setQueryScriptLanguage("ECMAScript"); - - dataset.loadData(); - IDataStore dataStore = dataset.getDataStore(); - assertNotNull(dataStore); - assertEquals(30, dataStore.getRecordsCount()); - IMetaData metaData = dataStore.getMetaData(); - assertNotNull(metaData); - assertEquals(1, metaData.getFieldCount()); - IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); - assertEquals("Full Name", fieldMetaData.getName()); - assertEquals(null, fieldMetaData.getAlias()); - assertEquals(String.class, fieldMetaData.getType()); - } - - public void testScriptedQueryWithParameters() { - Map parameters = new HashMap(); - parameters.put("limit", "5"); - dataset.setParamsMap(parameters); - - String script = "query.replace(\"LIMIT 10\",\"LIMIT \" + parameters.get('limit'));"; - dataset.setQueryScript(script); - dataset.setQueryScriptLanguage("ECMAScript"); - - dataset.loadData(); - IDataStore dataStore = dataset.getDataStore(); - assertNotNull(dataStore); - assertEquals(5, dataStore.getRecordsCount()); - IMetaData metaData = dataStore.getMetaData(); - assertNotNull(metaData); - assertEquals(1, metaData.getFieldCount()); - IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); - assertEquals("Full Name", fieldMetaData.getName()); - assertEquals(null, fieldMetaData.getAlias()); - assertEquals(String.class, fieldMetaData.getType()); - } - - public void testScriptedQueryWithAttributes() { - Map attributes = new HashMap(); - attributes.put("limit", "5"); - dataset.setUserProfileAttributes(attributes); - - String script = "query.replace(\"LIMIT 10\",\"LIMIT \" + attributes.get('limit'));"; - dataset.setQueryScript(script); - dataset.setQueryScriptLanguage("ECMAScript"); - - dataset.loadData(); - IDataStore dataStore = dataset.getDataStore(); - assertNotNull(dataStore); - assertEquals(5, dataStore.getRecordsCount()); - IMetaData metaData = dataStore.getMetaData(); - assertNotNull(metaData); - assertEquals(1, metaData.getFieldCount()); - IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); - assertEquals("Full Name", fieldMetaData.getName()); - assertEquals(null, fieldMetaData.getAlias()); - assertEquals(String.class, fieldMetaData.getType()); - } +// public void testSimpleScriptedQuery() { +// String injectedStatement = "SELECT lname AS \\\'Last Name\\\' FROM CUSTOMER LIMIT 30"; +// String script = "'" + injectedStatement + "';"; +// dataset.setQueryScript(script); +// dataset.setQueryScriptLanguage("ECMAScript"); +// +// dataset.loadData(); +// IDataStore dataStore = dataset.getDataStore(); +// assertNotNull(dataStore); +// assertEquals(30, dataStore.getRecordsCount()); +// IMetaData metaData = dataStore.getMetaData(); +// assertNotNull(metaData); +// assertEquals(1, metaData.getFieldCount()); +// IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); +// assertEquals("Last Name", fieldMetaData.getName()); +// assertEquals(null, fieldMetaData.getAlias()); +// assertEquals(String.class, fieldMetaData.getType()); +// } + +// public void testScriptedQueryTransform() { +// String script = "query.replace(\"LIMIT 10\",\"LIMIT 30\");"; +// dataset.setQueryScript(script); +// dataset.setQueryScriptLanguage("ECMAScript"); +// +// dataset.loadData(); +// IDataStore dataStore = dataset.getDataStore(); +// assertNotNull(dataStore); +// assertEquals(30, dataStore.getRecordsCount()); +// IMetaData metaData = dataStore.getMetaData(); +// assertNotNull(metaData); +// assertEquals(1, metaData.getFieldCount()); +// IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); +// assertEquals("Full Name", fieldMetaData.getName()); +// assertEquals(null, fieldMetaData.getAlias()); +// assertEquals(String.class, fieldMetaData.getType()); +// } +// +// public void testScriptedQueryWithParameters() { +// Map parameters = new HashMap(); +// parameters.put("limit", "5"); +// dataset.setParamsMap(parameters); +// +// String script = "query.replace(\"LIMIT 10\",\"LIMIT \" + parameters.get('limit'));"; +// dataset.setQueryScript(script); +// dataset.setQueryScriptLanguage("ECMAScript"); +// +// dataset.loadData(); +// IDataStore dataStore = dataset.getDataStore(); +// assertNotNull(dataStore); +// assertEquals(5, dataStore.getRecordsCount()); +// IMetaData metaData = dataStore.getMetaData(); +// assertNotNull(metaData); +// assertEquals(1, metaData.getFieldCount()); +// IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); +// assertEquals("Full Name", fieldMetaData.getName()); +// assertEquals(null, fieldMetaData.getAlias()); +// assertEquals(String.class, fieldMetaData.getType()); +// } +// +// public void testScriptedQueryWithAttributes() { +// Map attributes = new HashMap(); +// attributes.put("limit", "5"); +// dataset.setUserProfileAttributes(attributes); +// +// String script = "query.replace(\"LIMIT 10\",\"LIMIT \" + attributes.get('limit'));"; +// dataset.setQueryScript(script); +// dataset.setQueryScriptLanguage("ECMAScript"); +// +// dataset.loadData(); +// IDataStore dataStore = dataset.getDataStore(); +// assertNotNull(dataStore); +// assertEquals(5, dataStore.getRecordsCount()); +// IMetaData metaData = dataStore.getMetaData(); +// assertNotNull(metaData); +// assertEquals(1, metaData.getFieldCount()); +// IFieldMetaData fieldMetaData = metaData.getFieldMeta(0); +// assertEquals("Full Name", fieldMetaData.getName()); +// assertEquals(null, fieldMetaData.getAlias()); +// assertEquals(String.class, fieldMetaData.getType()); +// } } diff --git a/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/listener/DataStoreListenerOperatorTest.java b/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/listener/DataStoreListenerOperatorTest.java index 3db2b9815af..23029cc56c3 100644 --- a/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/listener/DataStoreListenerOperatorTest.java +++ b/knowageutils/src/test/java/it/eng/spagobi/tools/dataset/listener/DataStoreListenerOperatorTest.java @@ -760,14 +760,12 @@ public T getImplementation(Class clazz) { @Override public Map getDrivers() { - - return getDrivers(); + throw new UnsupportedOperationException("Not implemented"); } @Override public void setDrivers(Map drivers) { - - setDrivers(drivers); + throw new UnsupportedOperationException("Not implemented"); } @Override diff --git a/knowageutilsjson/src/main/java/org/json/JSONObject.java b/knowageutilsjson/src/main/java/org/json/JSONObject.java index 6639dbf8d4a..a5444df2f38 100644 --- a/knowageutilsjson/src/main/java/org/json/JSONObject.java +++ b/knowageutilsjson/src/main/java/org/json/JSONObject.java @@ -20,6 +20,7 @@ import java.io.Serializable; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.math.BigDecimal; import java.util.Collection; import java.util.Iterator; import java.util.Map; @@ -538,6 +539,8 @@ public JSONObject put(String key, Object value) throws JSONException { rootNode.put(key, (Float) wrappedValue); } else if (wrappedValue instanceof Double) { rootNode.put(key, (Double) wrappedValue); + } else if (wrappedValue instanceof BigDecimal) { + rootNode.put(key, (BigDecimal) wrappedValue); } else if (wrappedValue instanceof String) { rootNode.put(key, (String) wrappedValue); } else if (wrappedValue instanceof JSONObject) { diff --git a/knowageutilsjson/src/main/java/org/json/JacksonWrapper.java b/knowageutilsjson/src/main/java/org/json/JacksonWrapper.java index b31efa820a6..539a014b97a 100644 --- a/knowageutilsjson/src/main/java/org/json/JacksonWrapper.java +++ b/knowageutilsjson/src/main/java/org/json/JacksonWrapper.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,16 +11,17 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package org.json; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.Collection; import java.util.Map; -import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.BooleanNode; import com.fasterxml.jackson.databind.node.DoubleNode; @@ -29,113 +30,113 @@ import com.fasterxml.jackson.databind.node.NullNode; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; -import com.fasterxml.jackson.databind.node.ValueNode; /** * @author Andrea Gioia (andrea.gioia@eng.it) * */ public class JacksonWrapper { - - /** - * Wrap an object, if necessary. If the object is null, return the NullNode - * object. If it is an array or collection, wrap it in a ArrayNode. If - * it is a map, wrap it in a ObjectNode. If it is a standard property - * (Double, String, et al) then it is already wrapped. - * - * @param object The object to wrap - * @return The wrapped value - * @throws JSONException - */ - static final Object wrap(Object object) throws JSONException { - Object wrappedObject = null; - - try { - if (object == null || object.equals( JSONObject.NULL ) ) { - return NullNode.instance ; - } - - if ( object instanceof Byte || object instanceof Character || - object instanceof Short || object instanceof Integer || - object instanceof Long || object instanceof Boolean || - object instanceof Float || object instanceof Double || - object instanceof String) { - - wrappedObject = object; - - } else if(object instanceof JSONObject || object instanceof JSONArray) { - - wrappedObject = object; - - } else if(object instanceof ObjectNode) { - - wrappedObject = new JSONObject((ObjectNode)object); - - } else if(object instanceof ArrayNode) { - - wrappedObject = new JSONArray((ArrayNode)object); - - } else if (object instanceof Collection) { - - wrappedObject = wrap( new JSONArray((Collection)object) ); - - } else if (object.getClass().isArray()) { - - wrappedObject = wrap( new JSONArray(object) ); - - } else if (object instanceof Map) { - - wrappedObject = wrap (new JSONObject((Map)object)); - - } else { - //wrappedObject = new JSONObject(object); - wrappedObject = object.toString(); - } - - return wrappedObject; - - } catch(Throwable t) { - if(t instanceof JSONException) throw (JSONException)t; - throw new JSONException("An unexpected error occured while wrapping value [" + object + "] of type [" + (object!=null?object.getClass().getName(): "null") + "]: " + t.getMessage()); - } - } - - static final Object unwrap(Object object) throws JSONException { - Object unwrappedObject = null; - - try { - if ( object == NullNode.instance ) { - return JSONObject.NULL ; - } - - if(object instanceof TextNode) { - unwrappedObject = ((TextNode)object).asText(); - } else if(object instanceof IntNode) { - int v = ((IntNode)object).asInt(); - unwrappedObject = new Integer(v); - } else if(object instanceof LongNode) { - long v = ((LongNode)object).asLong(); - unwrappedObject = new Long(v); - } else if(object instanceof DoubleNode) { - double v = ((DoubleNode)object).asDouble(); - unwrappedObject = new Double(v); - } else if(object instanceof BooleanNode) { - boolean v = ((BooleanNode)object).asBoolean(); - unwrappedObject = new Boolean(v); - } else if(object instanceof ObjectNode) { - unwrappedObject = new JSONObject( (ObjectNode)object ); - } else if(object instanceof ArrayNode) { - unwrappedObject = new JSONArray( (ArrayNode)object ); - } else { - throw new JSONException("Unsupported value type [" + object.getClass().getName() + "]"); - } - - return unwrappedObject; - - } catch(Throwable t) { - if(t instanceof JSONException) throw (JSONException)t; - throw new JSONException("An unexpected error occured while wrapping value [" + object + "] of type [" + (object!=null?object.getClass().getName(): "null") + "]: " + t.getMessage()); - } + + /** + * Wrap an object, if necessary. If the object is null, return the NullNode object. If it is an array or collection, wrap it in a ArrayNode. If it is a map, + * wrap it in a ObjectNode. If it is a standard property (Double, String, et al) then it is already wrapped. + * + * @param object + * The object to wrap + * @return The wrapped value + * @throws JSONException + */ + static final Object wrap(Object object) throws JSONException { + Object wrappedObject = null; + + try { + if (object == null || object.equals(JSONObject.NULL)) { + return NullNode.instance; + } + + if (object instanceof Byte || object instanceof Character || object instanceof Boolean || object instanceof Short || object instanceof Integer + || object instanceof Long || object instanceof BigInteger || object instanceof Float || object instanceof Double + || object instanceof BigDecimal || object instanceof String) { + + wrappedObject = object; + + } else if (object instanceof JSONObject || object instanceof JSONArray) { + + wrappedObject = object; + + } else if (object instanceof ObjectNode) { + + wrappedObject = new JSONObject((ObjectNode) object); + + } else if (object instanceof ArrayNode) { + + wrappedObject = new JSONArray((ArrayNode) object); + + } else if (object instanceof Collection) { + + wrappedObject = wrap(new JSONArray((Collection) object)); + + } else if (object.getClass().isArray()) { + + wrappedObject = wrap(new JSONArray(object)); + + } else if (object instanceof Map) { + + wrappedObject = wrap(new JSONObject((Map) object)); + + } else { + // wrappedObject = new JSONObject(object); + wrappedObject = object.toString(); + } + + return wrappedObject; + + } catch (Throwable t) { + if (t instanceof JSONException) + throw (JSONException) t; + throw new JSONException("An unexpected error occured while wrapping value [" + object + "] of type [" + + (object != null ? object.getClass().getName() : "null") + "]: " + t.getMessage()); } - + } + + static final Object unwrap(Object object) throws JSONException { + Object unwrappedObject = null; + + try { + if (object == NullNode.instance) { + return JSONObject.NULL; + } + + if (object instanceof TextNode) { + unwrappedObject = ((TextNode) object).asText(); + } else if (object instanceof IntNode) { + int v = ((IntNode) object).asInt(); + unwrappedObject = new Integer(v); + } else if (object instanceof LongNode) { + long v = ((LongNode) object).asLong(); + unwrappedObject = new Long(v); + } else if (object instanceof DoubleNode) { + double v = ((DoubleNode) object).asDouble(); + unwrappedObject = new Double(v); + } else if (object instanceof BooleanNode) { + boolean v = ((BooleanNode) object).asBoolean(); + unwrappedObject = new Boolean(v); + } else if (object instanceof ObjectNode) { + unwrappedObject = new JSONObject((ObjectNode) object); + } else if (object instanceof ArrayNode) { + unwrappedObject = new JSONArray((ArrayNode) object); + } else { + throw new JSONException("Unsupported value type [" + object.getClass().getName() + "]"); + } + + return unwrappedObject; + + } catch (Throwable t) { + if (t instanceof JSONException) + throw (JSONException) t; + throw new JSONException("An unexpected error occured while wrapping value [" + object + "] of type [" + + (object != null ? object.getClass().getName() : "null") + "]: " + t.getMessage()); + } + } + } diff --git a/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/PivotJsonHTMLSerializer.java b/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/PivotJsonHTMLSerializer.java index 30aa254cb87..532108f17fd 100644 --- a/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/PivotJsonHTMLSerializer.java +++ b/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/PivotJsonHTMLSerializer.java @@ -27,7 +27,6 @@ import javax.xml.bind.JAXBException; import org.apache.log4j.Logger; -import org.hibernate.jdbc.util.BasicFormatterImpl; import org.json.JSONException; import org.olap4j.Axis; import org.olap4j.CellSet; @@ -460,17 +459,11 @@ private void serializeFunctions(String field, JsonGenerator jgen, SpagoBIPivotMo */ public String formatQueryString(String queryString) { - String formattedQuery; - BasicFormatterImpl fromatter; - if (queryString == null || queryString.equals("")) { logger.error("Impossible to get the query string because the query is null"); return ""; } - - fromatter = new BasicFormatterImpl(); - formattedQuery = fromatter.format(queryString); - return StringUtilities.fromStringToHTML(formattedQuery); + return StringUtilities.fromStringToHTML(queryString); } private void doPagination(boolean condition, ModelConfig modelConfig, SpagoBIPivotModel model, WhatIfHTMLRendereCallback callback, StringWriter writer, diff --git a/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/SpagoBIPivotModel.java b/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/SpagoBIPivotModel.java index f9d82c3dac1..c03e09437ae 100644 --- a/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/SpagoBIPivotModel.java +++ b/knowagewhatifengine/src/main/java/it/eng/spagobi/engines/whatif/model/SpagoBIPivotModel.java @@ -47,6 +47,7 @@ import org.pivot4j.sort.SortCriteria; import org.pivot4j.sort.SortMode; import org.pivot4j.transform.ChangeSlicer; +import org.pivot4j.transform.NonEmpty; import org.pivot4j.transform.SwapAxes; import org.pivot4j.util.OlapUtils; @@ -252,8 +253,7 @@ public void persistTransformations(Connection connection) throws WhatIfPersistin /** * Persist the modifications in the selected version * - * @param version - * the version of the model in witch persist the modification. In null persist in the version selected in the Version dimension + * @param version the version of the model in witch persist the modification. In null persist in the version selected in the Version dimension * @throws WhatIfPersistingTransformationException */ public void persistTransformations(Connection connection, Integer version) throws WhatIfPersistingTransformationException { @@ -406,31 +406,8 @@ public String getQueryWithOutCC() { } public void setNonEmpty(boolean suppressEmpty) { - - if (suppressEmpty) { - QueryAxis qaRows = getQueryAxis(Axis.ROWS); - QueryAxis qaColumns = getQueryAxis(Axis.COLUMNS); - - Exp rowsExp = qaRows.getExp(); - String notIsEmpty = "NOT isEmpty(Measures.currentMember)"; - - List rowsArgs = new ArrayList(2); - rowsArgs.add(rowsExp); - rowsArgs.add(Literal.createString(notIsEmpty)); - FunCall rowsFilter = new FunCall("Filter", Syntax.Function, rowsArgs); - qaRows.setExp(rowsFilter); - - Exp columnsExp = qaColumns.getExp(); - - List columsArgs = new ArrayList(2); - columsArgs.add(columnsExp); - columsArgs.add(Literal.createString(notIsEmpty)); - FunCall columnsFilter = new FunCall("Filter", Syntax.Function, columsArgs); - qaColumns.setExp(columnsFilter); - } - - fireModelChanged(); - + NonEmpty transform = this.getTransform(NonEmpty.class); + transform.setNonEmpty(suppressEmpty); } public void setSubset(Integer startRow, Integer startColumn, Integer rowSet, Integer columnSet) { diff --git a/knowagewhatifengine/src/main/java/it/eng/spagobi/pivot4j/ui/html/WhatIfHTMLRendereCallback.java b/knowagewhatifengine/src/main/java/it/eng/spagobi/pivot4j/ui/html/WhatIfHTMLRendereCallback.java index 307f88257aa..ab8480fb472 100644 --- a/knowagewhatifengine/src/main/java/it/eng/spagobi/pivot4j/ui/html/WhatIfHTMLRendereCallback.java +++ b/knowagewhatifengine/src/main/java/it/eng/spagobi/pivot4j/ui/html/WhatIfHTMLRendereCallback.java @@ -558,6 +558,7 @@ private void initializeInternal(TableRenderContext context) { } private void setSortingCommand(TableRenderContext context) { + String pathToImages = "../../../../knowage/themes/commons/img/olap/"; int axis = 0; if (context.getAxis() != null) { axis = context.getAxis().axisOrdinal(); @@ -577,9 +578,9 @@ private void setSortingCommand(TableRenderContext context) { if (context.getModel().getSortCriteria().equals(SortCriteria.ASC) || context.getModel().getSortCriteria().equals(SortCriteria.BASC) || context.getModel().getSortCriteria().equals(SortCriteria.TOPCOUNT)) { if (axisToSort == Axis.ROWS.axisOrdinal()) { - attributes.put("src", "../../img/DESC-rows.png"); + attributes.put("src", pathToImages + "DESC-rows.png"); } else { - attributes.put("src", "../../img/DESC-columns.png"); + attributes.put("src", pathToImages + "DESC-columns.png"); } attributes.put("ng-click", @@ -592,9 +593,9 @@ private void setSortingCommand(TableRenderContext context) { || context.getModel().getSortCriteria().equals(SortCriteria.BOTTOMCOUNT)) { if (axisToSort == Axis.ROWS.axisOrdinal()) { - attributes.put("src", "../../img/ASC-rows.png"); + attributes.put("src", pathToImages + "ASC-rows.png"); } else { - attributes.put("src", "../../img/ASC-columns.png"); + attributes.put("src", pathToImages + "ASC-columns.png"); } attributes.put("ng-click", @@ -607,9 +608,9 @@ private void setSortingCommand(TableRenderContext context) { } else { context.getModel().setSorting(false); if (axisToSort == Axis.ROWS.axisOrdinal()) { - attributes.put("src", "../../img/noSortRows.png"); + attributes.put("src", pathToImages + "noSortRows.png"); } else { - attributes.put("src", "../../img/noSortColumns.png"); + attributes.put("src", pathToImages + "noSortColumns.png"); } attributes.put("ng-click", diff --git a/knowagewhatifengine/src/main/webapp/META-INF/context.xml b/knowagewhatifengine/src/main/webapp/META-INF/context.xml index b5eae04b105..ea53b75f7fa 100644 --- a/knowagewhatifengine/src/main/webapp/META-INF/context.xml +++ b/knowagewhatifengine/src/main/webapp/META-INF/context.xml @@ -9,5 +9,5 @@ - - + + diff --git a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp index 638c0b45b02..cf25f15f764 100644 --- a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp +++ b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularImport.jsp @@ -21,7 +21,8 @@ along with this program. If not, see . - + "/> + "/> @@ -64,5 +65,6 @@ along with this program. If not, see . + "> <%@include file="/WEB-INF/jsp/commons/angular/sbiModule.jspf"%> \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf index 0b5350a7998..a37ff4982b4 100644 --- a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf +++ b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/commons/angular/angularResource.jspf @@ -15,9 +15,6 @@ GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . --> -<%-- -author:... ---%> <%@page import= "it.eng.spagobi.engines.whatif.common.WhatIfConstants" %> <%@page import= "java.util.Enumeration" %> @@ -45,6 +42,7 @@ author:... <%@page import="java.util.ArrayList"%> <%@page import="it.eng.spagobi.commons.bo.UserProfile"%> <%@page import="it.eng.spagobi.utilities.engines.EngineStartServletIOManager"%> +<%@page import="it.eng.knowage.commons.utilities.urls.UrlBuilder"%> @@ -55,6 +53,10 @@ author:... <%-- ---------------------------------------------------------------------- --%> <% + String spagoBiContext = request.getParameter("SBICONTEXT"); + String thisContext = request.getContextPath(); + UrlBuilder urlBuilder = new UrlBuilder(spagoBiContext, thisContext); + WhatIfEngineInstance whatIfEngineInstance; //UserProfile profile; Locale locale =null; diff --git a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/edit.jsp b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/edit.jsp index 2fc06f4df43..044cf81db9f 100644 --- a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/edit.jsp +++ b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/edit.jsp @@ -9,9 +9,7 @@ <%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> <%@include file="/WEB-INF/jsp/commons/olap/olapImport.jsp"%> - - - + OLAP Designer - + diff --git a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/whatIf2.jsp b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/whatIf2.jsp index 0bf465580c2..37d837887cf 100644 --- a/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/whatIf2.jsp +++ b/knowagewhatifengine/src/main/webapp/WEB-INF/jsp/whatIf2.jsp @@ -6,52 +6,42 @@ - -<%@include file="/WEB-INF/jsp/commons/angular/angularImport.jsp"%> -<%@include file="/WEB-INF/jsp/commons/olap/olapImport.jsp"%> - - - -OLAP - + + - - - - - - - - - - -
+ +
- - - - +
-
- - - + + \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/css/customStyle.css b/knowagewhatifengine/src/main/webapp/css/customStyle.css deleted file mode 100644 index e0a03907159..00000000000 --- a/knowagewhatifengine/src/main/webapp/css/customStyle.css +++ /dev/null @@ -1,789 +0,0 @@ - -md-toolbar.md-knowage-theme { - background-color: #3b678c !important; - color: #fff !important -} - -md-toolbar.md-knowage-theme .md-toolbar-tools { - height: 40px; - font-size: 15px; - text-transform: uppercase; - font-weight: 600 -} - -div.md-button:first-child ._md-list-item-inner{ - height:auto !important -} - - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Regular-webfont.eot"); - src: url("../fonts/roboto/Roboto-Regular-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Regular-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Regular-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Regular-webfont.svg#RobotoRegular") format("svg") -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Italic-webfont.eot"); - src: url("../fonts/roboto/Roboto-Italic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Italic-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Italic-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Italic-webfont.svg#RobotoItalic") format("svg"); - font-weight: normal; - font-style: italic -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Bold-webfont.eot"); - src: url("../fonts/roboto/Roboto-Bold-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Bold-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Bold-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Bold-webfont.svg#RobotoBold") format("svg"); - font-weight: bold; - font-style: normal -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-BoldItalic-webfont.eot"); - src: url("../fonts/roboto/Roboto-BoldItalic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-BoldItalic-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-BoldItalic-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-BoldItalic-webfont.svg#RobotoBoldItalic") format("svg"); - font-weight: bold; - font-style: italic -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Thin-webfont.eot"); - src: url("../fonts/roboto/Roboto-Thin-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Thin-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Thin-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Thin-webfont.svg#RobotoThin") format("svg"); - font-weight: 200; - font-style: normal -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-ThinItalic-webfont.eot"); - src: url("../fonts/roboto/Roboto-ThinItalic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-ThinItalic-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-ThinItalic-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-ThinItalic-webfont.svg#RobotoThinItalic") format("svg"); - font-weight: 200; - font-style: italic -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Light-webfont.eot"); - src: url("../fonts/roboto/Roboto-Light-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Light-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Light-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Light-webfont.svg#RobotoLight") format("svg"); - font-weight: 100; - font-style: normal -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-LightItalic-webfont.eot"); - src: url("../fonts/roboto/Roboto-LightItalic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-LightItalic-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-LightItalic-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-LightItalic-webfont.svg#RobotoLightItalic") format("svg"); - font-weight: 100; - font-style: italic -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-Medium-webfont.eot"); - src: url("../fonts/roboto/Roboto-Medium-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-Medium-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-Medium-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-Medium-webfont.svg#RobotoMedium") format("svg"); - font-weight: 300; - font-style: normal -} - -@font-face { - font-family: 'Roboto'; - src: url("../fonts/roboto/Roboto-MediumItalic-webfont.eot"); - src: url("../fonts/roboto/Roboto-MediumItalic-webfont.eot?#iefix") format("embedded-opentype"), url("../fonts/roboto/Roboto-MediumItalic-webfont.woff") format("woff"), url("../fonts/roboto/Roboto-MediumItalic-webfont.ttf") format("truetype"), url("../fonts/roboto/Roboto-MediumItalic-webfont.svg#RobotoMediumItalic") format("svg"); - font-weight: 300; - font-style: italic -} - - -.kn-list { - background: #eceff1; - border-right: 2px solid gray -} - -.kn-list md-icon.fa { - padding-left: 2px; - display: inline -} - -.kn-list md-content.md-knowage-theme { - background-color: transparent -} - -.kn-detail { - background: #f6f6f6 -} - -.kn-detail .kn-detail-content { - background: transparent -} - -.kn-detail .containerDiv { - position: absolute -} - -.kn-detail .layerFilter { - padding: 10px -} - -.kn-detail md-content .layerFilterContent { - overflow: hidden -} - -.kn-detail .angularListTemplate .searchBarList input { - margin: 0px; - padding-left: 18px; - height: initial -} - -.kn-detail .md-button.md-knowage-theme.md-fab { - top: 0px -} - -.kn-detail .md-button.md-knowage-theme.md-fab md-icon { - font-size: inherit; - padding-top: inherit -} - -.kn-detail .angularListTemplate { - font-family: Roboto, Verdana, Geneva, Arial, Helvetica, sans-serif -} - - -angular-table table>tbody>tr>td { - font-size: 16px; - border-top: 1px #c3d4df solid; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden -} - -angular-table table>thead { - background: white -} - -angular-table { - padding: 0 5px; - overflow: auto; - overflow-y: hidden; - min-height: 200px -} - -angular-table angular-table-actions { - margin-top: 15px; - margin-bottom: 10px -} - -angular-table table thead th { - text-align: left; - font-size: 16px; - color: #3b678c; - font-weight: 600 -} - -angular-table table>tbody>tr.selectedRowItem { - background-color: #a9c3db -} - -angular-table table>tbody>tr:hover { - cursor: pointer; - background-color: #EEEEEE -} - -angular-table table thead th div { - align-items: center; - height: 40px; - line-height: 40px -} - -angular-table *:focus { - outline: none -} - -angular-table .hidden { - display: none !important -} - -angular-table .black { - color: black -} - -angular-table[no-pagination] #angularTableContentBox { - overflow-y: auto -} - -angular-table[full-width] #angularFullTableContentBox { - width: 100%; - overflow: auto -} - -angular-table[full-width] #angularTableContentBox { - overflow-x: hidden -} - -angular-table[full-width] table { - width: auto !important -} - -angular-table table { - width: 100%; - table-layout: fixed; - border-spacing: 0 -} - -angular-table[multi-select] table>thead>tr>th:nth-child(n+3):nth-last-child(n+2), -angular-table[multi-select] table>tbody>tr>td:nth-child(n+3):nth-last-child(n+2), -angular-table:not(multi-select) table>thead>tr>th:nth-child(n+1):nth-last-child(n+2), -angular-table:not(multi-select) table>tbody>tr>td:nth-child(n+1):nth-last-child(n+2) { - padding: 0 10px -} - -angular-table[multi-select] table>thead>tr>th:nth-child(2), -angular-table:not(multi-select) table>thead>tr>th:nth-child(1), -angular-table[multi-select] table>tbody>tr>td:nth-child(2), -angular-table:not(multi-select) table>tbody>tr>td:nth-child(1) { - padding: 0 10px 0 0 !important -} - -angular-table table>thead>tr>th:last-child, -angular-table table>tbody>tr>td:last-child { - padding: 0 10px -} - -angular-table table thead th div md-icon { - margin-top: 9px; - width: 7px -} - -angular-table table>tbody>tr { - height: 2em; - transition: background-color .2s -} - -angular-table table>tbody>tr>td { - font-size: 13px; - color: rgba(0, 0, 0, 0.87); - border-top: 1px rgba(0, 0, 0, 0.12) solid; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden -} - -angular-table table>thead>tr>th>div { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden -} - -angular-table table>tbody>tr>td button.actionButton { - height: 30px !important; - width: 30px !important; - min-height: 25px !important; - margin: 0 !important -} - -angular-table table>tbody>tr>td button.actionButton:hover { - background-color: #C0C9D0 !important -} - -@-moz-document url-prefix() { - angular-table table>tbody>tr>td { - text-overflow: inherit - } -} - -angular-table table td div { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - line-height: 26px -} - -angular-table angular-table-actions md-input-container.tableSearchBar { - padding-bottom: 0px; - height: 25px -} - -angular-table angular-table-actions { - padding: 0 24px 0 10px; - height: 30px -} - -angular-table angular-table-actions md-input-container.tableSearchBar .closeSearchBar { - left: 100%; - margin-left: -15px -} - -angular-table .fakeTable md-checkbox.md-knowage-theme { - margin: 0 -} - -angular-table .fakeTable tr th:first-child *:not(md-checkbox) div:not(.md-icon) { - margin-left: 10px -} - -angular-table .principalTable tr th:first-child *:not(md-checkbox) div:not(.md-icon) { - margin-left: 10px -} - -angular-table .fakeTable tr th:first-child>div:not(.md-icon) { - margin-left: 10px -} - -angular-table .principalTable tr th:first-child>div:not(.md-icon) { - margin-left: 10px -} - -angular-table .principalTable tr td:first-child>span { - margin-left: 10px -} - -angular-table .pagination>li, -angular-table .pagination>li>span { - position: relative; - float: left; - margin-left: -1px; - text-decoration: none !important; - background-color: #fff; - border: 1px solid #ccc; - display: block; - width: 30px; - height: 28px; - text-align: center; - line-height: 28px -} - -angular-table .pagination { - margin: 0px !important; - padding: 0px !important -} - -angular-table .pagination>li>a { - text-decoration: none !important; - width: 100%; - display: block; - font-size: 12px; - color: #3b678c -} - -angular-table .pagination>li>a:hover { - background-color: #f1f5f9 -} - -angular-table .pagination>.active, -angular-table .pagination>.active>a, -angular-table .pagination>.active>a:focus, -angular-table .pagination>.active>a:hover, -angular-table .pagination>.active>span, -angular-table .pagination>.active>span:focus, -angular-table .pagination>.active>span:hover { - z-index: 2; - color: #000; - cursor: default; - background-color: #a9c3db; - border-color: #a9c3db -} - -angular-table .pagination>.disabled>a, -angular-table .pagination>.disabled>a:focus, -angular-table .pagination>.disabled>a:hover, -angular-table .pagination>.disabled>span, -angular-table .pagination>.disabled>span:focus, -angular-table .pagination>.disabled>span:hover { - color: #777; - cursor: not-allowed; - background-color: #ddd; - border-color: #ddd -} - -angular-table .dropdown_menu_list { - position: fixed !important -} - -angular-table .position-fixed { - position: fixed !important -} - -angular-table .dropdown_menu_list md-list { - position: relative; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - text-align: left; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - background-color: #ECECEC -} - -angular-table .dropdown_menu_list.open md-list { - display: block -} - -angular-table .dropdown_menu_list md-list-item, -angular-table .dropdown_menu_list md-list-item button, -angular-table .dropdown_menu_list md-list-item .md-list-item-inner { - min-height: 22px !important -} - -angular-table .dropdown_menu_list md-list-item p { - line-height: 20px; - margin: 3px; - color: black -} - -angular-table .dropdown_menu_list md-list.bottomBorder md-list-item button { - border-bottom: 1px solid #b0bec5; - padding: 0; - margin-left: 8px; - margin-right: 8px; - border-radius: 0 -} - -angular-table md-checkbox { - margin-bottom: 0px -} - -angular-table .tableDragBar { - padding: 0 !important; - text-align: center; - color: grey -} - -angular-table .animate-repeat-tablerow.ng-move, -angular-table .animate-repeat-tablerow.ng-enter { - transition: all linear 0.2s -} - -angular-table .animate-repeat-tablerow.ng-leave.ng-leave-active, -angular-table .animate-repeat-tablerow.ng-move, -angular-table .animate-repeat-tablerow.ng-enter { - opacity: 0 -} - -angular-table .animate-repeat-tablerow.ng-leave, -angular-table .animate-repeat-tablerow.ng-move.ng-move-active, -angular-table .animate-repeat-tablerow.ng-enter.ng-enter-active { - opacity: 1 -} - -angular-table .animate-repeat-tablerow.ng-leave, -angular-table .animate-repeat-tablerow.ng-leave.ng-leave-active { - transition: all 0s -} - -angular-table.absoluteTfoot tfoot>tr>td #queueTableContent { - display: none -} - -angular-table.absoluteTfoot #fixedAngularTableContentBox { - display: block -} - -angular-table #fixedAngularTableContentBox { - display: none -} - -angular-table .principalTable>thead>tr>th>div { - height: 0px !important -} - -angular-table .principalTable>thead>tr>th>md-checkbox { - display: none -} - -angular-table .principalTable>thead>tr>th { - padding-top: 0px !important; - padding-bottom: 0px !important -} - -angular-table md-radio-button ._md-container { - left: 20px; - top: 10px -} - -@-moz-document url-prefix() { - angular-table md-radio-button ._md-container { - left: 20px; - top: 0px - } -} - - -.md-button.md-knowage-theme.md-fab { - top: 10px -} - -.md-button.md-knowage-theme.md-fab:not([disabled]) { - background-color: #c70751 !important -} - -.md-button.md-knowage-theme.md-fab md-icon { - font-size: 18px; - padding-top: 4px -} - -md-input-container.md-knowage-theme .md-input { - border-color: #3b678c -} - -md-input-container .md-errors-spacer{ - display:none; -} - -md-input-container.md-knowage-theme:not(.md-input-invalid).md-input-focused .md-input { - border-color: #3b678c -} - - -md-input-container.md-knowage-theme:not(.md-input-invalid).md-input-focused md-icon { - color: #3b678c -} - -md-input-container.md-knowage-theme:not(.md-input-invalid).md-input-has-value label { - color: #a9c3db -} - -md-input-container.md-knowage-theme:not(.md-input-invalid).md-input-focused label { - color: #3b678c -} - -md-input-container.md-knowage-theme ng-messages:not(.md-char-counter), -md-input-container.md-knowage-theme [ng-messages]:not(.md-char-counter), -md-input-container.md-knowage-theme ng-message:not(.md-char-counter), -md-input-container.md-knowage-theme data-ng-message:not(.md-char-counter), -md-input-container.md-knowage-theme x-ng-message:not(.md-char-counter), -md-input-container.md-knowage-theme [ng-message]:not(.md-char-counter), -md-input-container.md-knowage-theme [data-ng-message]:not(.md-char-counter), -md-input-container.md-knowage-theme [x-ng-message]:not(.md-char-counter), -md-input-container.md-knowage-theme [ng-message-exp]:not(.md-char-counter), -md-input-container.md-knowage-theme [data-ng-message-exp]:not(.md-char-counter), -md-input-container.md-knowage-theme [x-ng-message-exp]:not(.md-char-counter) { - color: #c70751 -} - -md-input-container.md-knowage-theme.md-input-invalid .md-input { - border-color: #c70751 -} - -md-input-container.md-knowage-theme.md-input-invalid.md-input-focused label { - color: #c70751 -} - -md-checkbox.md-knowage-theme.md-checked .md-icon { - background-color: #3b678c -} - -md-checkbox.md-knowage-theme .md-icon { - border-color: #3b678c -} - -md-radio-button.md-knowage-theme .md-on { - background-color: #3b678c -} - -md-radio-button.md-knowage-theme .md-off { - border-color: #a9c3db -} - -md-radio-button.md-knowage-theme.md-checked .md-off { - border-color: #a9c3db -} - -md-select.md-knowage-theme .md-select-value { - border-bottom-color: #3b678c -} - -md-select.md-knowage-theme .md-select-value .md-select-icon { - color: #3b678c -} - -md-select.md-knowage-theme:not([disabled]):focus .md-select-value { - border-bottom-color: #3b678c -} - -md-select-menu.md-knowage-theme md-option[selected] { - color: #3b678c -} - -md-select-menu.md-knowage-theme md-option[selected]:focus { - color: #3b678c -} - -md-tabs.md-knowage-theme .md-tab.md-active, -md-tabs.md-knowage-theme .md-tab.md-active md-icon, -md-tabs.md-knowage-theme .md-tab.md-focused, -md-tabs.md-knowage-theme .md-tab.md-focused md-icon { - color: #3b678c; - font-weight: 500 -} - -md-tabs.md-knowage-theme md-ink-bar { - color: #3b678c; - background: #3b678c -} - -md-card.md-knowage-theme { - background-color: #fff; - display: block; - padding: 8px -} - -md-tab-content md-content.md-knowage-theme { - background-color: transparent -} - -a.md-button.md-knowage-theme.md-primary, -.md-button.md-knowage-theme.md-primary { - color: #3b678c -} - -.md-button.md-knowage-theme.md-raised { - color: #3b678c; - background-color: #a9c3db -} - -.md-button.md-knowage-theme.md-raised:not([disabled]):hover { - background-color: #3b678c; - color: white -} - -.md-knowage-theme .md-calendar-date.md-calendar-selected-date .md-calendar-date-selection-indicator, -.md-knowage-theme .md-calendar-date.md-focus.md-calendar-selected-date .md-calendar-date-selection-indicator { - background: #3b678c; - color: #fff; - border-color: transparent -} - -.md-knowage-theme .md-calendar-date-selection-indicator:hover { - background: #a9c3db -} - -.md-knowage-theme .md-datepicker-input-container { - border-bottom-color: #3b678c -} - -.md-knowage-theme .md-datepicker-input-container.md-datepicker-focused { - border-bottom-color: #3b678c -} - -.md-knowage-theme .md-datepicker-input { - color: #3b678c -} - -.md-knowage-theme .md-datepicker-triangle-button .md-datepicker-expand-triangle { - border-top-color: #3b678c -} - -.md-knowage-theme .md-datepicker-triangle-button:hover .md-datepicker-expand-triangle { - border-top-color: #3b678c -} - -.md-knowage-theme .md-calendar-day-header { - background: #3b678c; - color: #fff -} - -.md-knowage-theme .md-calendar-date.md-calendar-date-today .md-calendar-date-selection-indicator { - border: 1px solid #3b678c -} - -.md-knowage-theme .md-calendar-date.md-focus .md-calendar-date-selection-indicator { - background: #a9c3db -} - -.kn-info { - margin: 10px; - border: 1px dashed #3b678c; - padding: 10px; - text-align: center; - position: relative -} - -.kn-close-Info { - position: absolute; - right: 5px; - top: 5px -} - -.ellipsis { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap -} - -.noMargin { - margin: 0px -} - -.noPadding { - padding: 0px -} - -.noBorder { - border: 0px -} - -.removeTransition { - transition: none !important -} - -.pagination > li, .pagination > li > span { - position: relative; - float: left; - margin-left: -1px; - text-decoration: none !important; - background-color: #fff; - border: 1px solid $bordersColor; - display: block; - width: 30px; - height: 28px; - text-align: center; - line-height: 28px; - } -​ - .pagination { - margin: 0px !important; - padding: 0px !important; - } -​ - .pagination > li > a { - text-decoration: none !important; - width: 100%; - display: block; - font-size: $smallFontSize; - color: $baseColor; - &:hover { - background-color: lighten($secondaryColor,20%); - } - } -​ - .pagination > .active, .pagination > .active > a, - .pagination > .active > a:focus, .pagination > .active > a:hover, - .pagination > .active > span, .pagination > .active > span:focus, - .pagination > .active > span:hover { - z-index: 2; - color: #000; - cursor: default; - background-color: $secondaryColor; - border-color: $secondaryColor; - } -​ - .pagination > .disabled > a, .pagination > .disabled > a:focus, - .pagination > .disabled > a:hover, - .pagination > .disabled > span, .pagination > .disabled > span:focus, - .pagination > .disabled > span:hover { - color: #777; - cursor: not-allowed; - background-color: #ddd; - border-color: #ddd; - } \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/css/olap.css b/knowagewhatifengine/src/main/webapp/css/olap.css deleted file mode 100644 index 17eefcac8ff..00000000000 --- a/knowagewhatifengine/src/main/webapp/css/olap.css +++ /dev/null @@ -1,955 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - - .loadingMask{ - position: fixed; - z-index:500; - height: 100%; - width: 100%; - background-color: black; - opacity :0.5; - } - - .loadingNoMask{ - position: fixed; - z-index:500; - height: 100%; - width: 100%; - - } - - .BUTTON_SAVE_SUBOBJECT{ - background-image: url(../img/savesuboject.png); - } - -.BUTTON_HIDE_SPANS_CLICKED{ - background-image: url(../img/hide_spans_clicked.png); -} - -.BUTTON_SHOW_PROPERTIES_CLICKED{ - background-image: url(../img/show_props_clicked.png); -} -.BUTTON_SHOW_COMPACT_PROPERTIES_CLICKED{ - background-image: url(../img/show_compact_props_clicked.png); -} - -.BUTTON_FATHER_MEMBERS_CLICKED{ - background-image: url(../img/show_parent_members_clicked.png); -} - -.BUTTON_HIDE_EMPTY_CLICKED{ - background-image: url(../img/empty_rows_clicked.png); -} -.BUTTON_EDITABLE_EXCEL_EXPORT{ - background-image: url(../img/editable_excel.png); -} -.knowage-blue { - background-color: #3b678c !important; - min-height: 0px !important; -} - -.BUTTON_ALGORITHMS{ - background-image: url(../img/alg_btn.png); - background-size: 30px; -} - -/*changed by @nsimovic*/ -.top-alignment{ - height:100%; -} - -/*changed by @aghedin*/ -.top-alignment-auto-height{ - min-height:85px; - max-height:85px -} - -/*added by @nsimovic*/ -.table-alignment { - position:absolute; - top:0px; - max-width: calc(100% - 52px); - } - - - -.groupX { - font-size: 12px; - margin: 10px 0px 10px 2px; - color:#000000 !important; - background-color: rgba(224, 224, 224, 0.96); - text-transform: none; - font-weight: 400; - line-height:1; - min-width:60px; - height: 25px; -} - -.md-button.left { - border-radius: 20px 0 0 20px; -} - -.md-button.middle { - border-radius: 0; - border-left: 1px solid rgba(230, 230, 230, 0.96); - border-right: 1px solid rgba(230, 230, 230, 0.96); -} - -.md-button.right { - border-radius: 0 25px 25px 0; -} - -.md-button:not([disabled]):hover { - background-color: rgba(193, 193, 193, 0.96); - transition: 0.3s; -} - -.md-button.dimension-top{ - background-color: rgba(59, 103, 140, 0.96); - height:25px; - font-size: 12px; - line-height: 1; - color:#ffffff !important; - border: 2px solid #ffffff; -} - -.md-button.dimension-left{ - background-color: rgba(59, 103, 140, 0.96); - height:25px; - font-size: 12px; - line-height: 1; - color:#ffffff !important; - transform: rotate(90deg); - margin-top: 55px; - margin-bottom: 20px; - margin-left:-29px; - border: 2px solid #ffffff; - padding: 4px; -} - -.md-button{ - min-height:0px; -} - -.main-toolbar-button{ - min-width:32px; - min-height:0px; - height:32px; - background-position:center; - background-repeat: no-repeat; -} -.dimension-top-toolbar{ - width:95% -} - -.dimension-top-toolbar .multi-hierarachy-btn{ - width: 20% !important; - min-width: 0px; - margin: 3% 0px 0px 0% !important; - line-height: 1; - padding: 0 10% 0 0; - } - -@-moz-document url-prefix() { - .dimension-top-toolbar .multi-hierarachy-btn{ - width: 20% !important; - min-width: 0px; - margin: 20% 0px 0px 0% !important; - line-height: 1; - padding: 0 15% 0 0; - } -} - -.dimension-left-toolbar{ - width:32px; -} - -.dimension-left-toolbar .multi-hierarachy-btn{ - width: 90% !important; - min-width: 0px; - margin: 20% 0px 0px 0% !important; - line-height: 1; - padding: 0 15% 0 0; -} - -.dimension-left-toolbar .multi-hierarachy-btn:hover{ - background-color:none; -} -.md-toolbar-tools{ - height: 32px; - padding:0px !important; -} - -.dialog-toolbar{ - padding: 0px 10px !important; -} - -.icon{ - height:32px; - min-width: 32px; -} - -.filter-toolbar{ - color: #ffffff !important; - border-radius: 10px 10px 0px 0px; - padding-left: 10px; - line-height: 0; -} - -/*New stuff start*/ -.filter-toolbar-element{ - background-color:#3b678c; - border-radius:5px; - border:1px solid white; - margin-right: 10px; - cursor: pointer; - font-weight: normal; - font-size: 15px !important; - line-height: 1.5; - max-height:28px; - max-width: 160px; - min-width: 140px; -} - -.filter-toolbar-element.dragging { - position:relative; - z-index:9; -} - -.filter-toolbar-element .name{ - width:80%; - padding-left:5px; - border-right:2px solid white; - overflow: hidden; - white-space: nowrap; -} - -.filter-toolbar-element .action{ - width:20%; -} - -.filter-toolbar-element .button, .filter-toolbar-element-left .button{ - margin: 0; - padding: 0; - width: 28px; - height: 24px; -} - -/**/ - -.filter-toolbar-element-left{ - border: 1px solid #FFF; - width: 80%; - border-radius: 5px; - margin-left: 4%; - margin-top: 2%; - margin-bottom:10px; - font-weight: normal; - font-size: 15px !important; - color:white; - cursor: pointer; - background-color:#3b678c; - min-height: 120px; - max-height: 130px; -} - -.filter-toolbar-element-left.dragging { - z-index: 9; - position: relative; -} - -.filter-toolbar-element-left .name{ - - padding-left:5px; - overflow: hidden; - min-height:95px; - max-height:100px; - white-space: nowrap; -} - -.filter-toolbar-element-left .name-multi{ - - padding-left:5px; - overflow: hidden; - min-height:70px; - max-height:90px; - white-space: nowrap; -} - -.filter-toolbar-element-left .action{ - border-top: 2px solid white; - max-height:20px; -} - -.filter-toolbar-element-left md-icon{ - color:white; -} - -.rotate-text{ - transform: rotate(90deg); - padding:5px; -} - -.rotate-text-nop{ - transform: rotate(90deg); -} -/*new stuff end*/ - - -md-card{ - border-radius: 10px 10px; -} - -md-tabs .md-tab.md-active{ - color:#3b678c !important; -} - -.central-panel{ -/* height:calc(100% - 120px); */ -/* width:100%; */ -/* position:absolute; */ -/* bottom:10px; */ -} - - - -.dialog-style{ - padding: 10px; -} - - - - - - -/*.tree css*/ - -.tree, -.tree ul { - margin:0 0 0 1em; /* indentation */ - padding:0; - list-style:none; - position:relative; -} - -.tree ul { - margin-left:.5em -} /* (indentation/2) */ - -.tree:before, -.tree ul:before { - content:""; - display:block; - width:0; - position:absolute; - top:0; - bottom:0; - left:0; - border-left:1px dotted #D3C1C1; -} - -.tree li { - margin:0; - padding: 0px 0.8em; - line-height: 2.3em; /* default list item's `line-height` */ - position:relative; - cursor:pointer; -} - -.tree li:before { - content:""; - display:block; - width:10px; /* same with indentation */ - height:0; - border-top:1px dotted #D3C1C1; - margin-top:-1px; /* border top width */ - position:absolute; - top:1em; /* (line-height/2) */ - left:0; -} - -.tree li:last-child:before { - background:white; /* same with body background */ - height:auto; - top:1em; /* (line-height/2) */ - bottom:0; -} - -.mdx-dialog{ - padding-left: 32px; - padding-right: 32px; -} - -.BUTTON_SORTING{ - background-image: url(../img/sorting-enabled.png); - background-size:23px 23px; -} - -.BUTTON_SORTING_CLICKED{ - background-image: url(../img/sorting-enabled_clicked.png); - background-size:23px 23px; -} -.BUTTON_CC{ - background-image: url(../img/cc.png); - background-size:23px 23px; -} - -.BUTTON_SORTING_SETTINGS{ - background-image: url(../img/sorting-settings.png); - background-size:23px 23px; -} - -.BUTTON_SCENARIO_WIZARD{ - background-image: url(../img/olapDesignerScenario.png); - background-size:23px 23px; -} -.BUTTON_CROSSNAV_WIZARD{ - background-image: url(../img/olapDesignerCross.png); - background-size:23px 23px; -} - -.BUTTON_PAGINATION_WIZARD{ - background-image: url(../img/olapDesignerPagination.png); - background-size:23px 23px; -} -.BUTTON_WIZARD{ - background-image: url(../img/olapDesignerButtons.png); - background-size:23px 23px; -} -.BUTTON_CROSS_NAVIGATION{ - background-image: url(../img/cross-navigation.png); - background-size:10px 10px; -} - -.highlight-filter-result{ - background-color: rgba(255,89,145,0.7); - border-radius: 5px; - padding: 2px; -} - -md-dialog.fullscreen-dialog { - max-width: 100%; - max-height: 100%; - width: 100%; - height: 100%; - border-radius: 0; -} - -.selected { - color: white; - -webkit-box-shadow:inset 0px 0px 0px 2px #3b678c; - -moz-box-shadow:inset 0px 0px 0px 2px #3b678c; - box-shadow:inset 0px 0px 0px 2px #3b678c; -} - -.filter-search{ - border: 1px solid; - border-radius: 5px; - width: 50%; - padding-left:5px; -} - -.filter-search-redbg{ - background-color: rgba(255,0,0, 0.3) -} - -.right-panel-buttons{ - padding: 1%; - margin: 10% ; - width:80%; - height:4%; - background-color:none; - min-width: 0px; -} - -@-moz-document url-prefix() { - .right-panel-buttons{ - height:70%; - } -} - -.selected-right-panel-buttons{ - padding: 1%; - margin: 10% ; - width:80%; - height:4%; - background-color:none; - min-width: 0px; - border: 1px solid red; -} -@-moz-document url-prefix() { - .selected-right-panel-buttons{ - height:70%; - } -} - -.customization-button{ - max-height: 32px; - padding-top: 10%; - min-width: 0px; - margin:0px 0px 0px 30%!important; - } - -@-moz-document url-prefix() { - .customization-button{ - max-height: 32px; - padding-top: 25%; - min-width: 0px; - margin:0px 0px 0px 25%!important; - } -} -.customization-button:hover{ - background: #4b85b4 !important; -} - -.right-toolbar{ - padding-top:35%; - padding-bottom:36%; -} - -@-moz-document url-prefix() { - .right-toolbar{ - padding-top:23%; - padding-bottom:23%; - } -} - -.right-menu{ - padding-top:2%; - padding-bottom:1%; -} - -@-moz-document url-prefix() { - .right-menu{ - padding-top:2%; - padding-bottom:2%; - } -} - -.md-sidenav-right{ - width:12%; - min-width:180px; -} - -@-moz-document url-prefix() { - .md-sidenav-right{ - width:13%; - min-width:180px; - } -} - -.right-toolbar-menu{ - height: 70%; - width: 60%; - background-repeat: no-repeat; - background-position: center center; - background-color:lightgrey; - min-width:60% !important; -} - -.menu-text{ - padding: 5% 5% 0px; - color: grey; - font-size: 90%; -} - -.drill-buttons{ - background-color: lightgrey; - height: 25px; - line-height: 1; - text-transform: none; - min-width:95%; - font-size:12px; -} - -@-moz-document url-prefix() { - .drill-buttons{ - font-size:10px; - } -} -.drill-buttons .left{ - border-radious:20% 0px 0px 20% !important -} - -.drill-buttons .right{ - border-radious:0px 20% 20% 0px!important -} - -.drill-buttons .middle{ - border-radious:0%!important -} - -/*New filter card*/ -.new-filter-card{ - min-width:160px; - max-width:240px; - border-radius:10px; - margin: 5px; - height: 70px; - cursor: pointer; - min-height:50px; -} - -@-moz-document url-prefix() { - .new-filter-card{ - width:13%; - min-width:180px; - border-radius:10px; - margin: 5px; - height: 85%; - cursor: pointer; - } -} - -.new-filter-card .top{ - height:50%; - border-radius: 10px 10px 0px 0px; - border: 1px solid; - background-color:#3b678c; -} - -.new-filter-card .top .button-area{ - width:20%; -} - -.new-filter-card .top .button-area .multi-hierarachy-btn{ - width: 20px !important; - height: 20px; - min-width: 0px; - margin: 5% 0px 0px 15% !important; - line-height: 1; - padding-left:0px; - padding-top:10%; -} - -.multi-hierarachy-btn:hover{ - background-color:inherit!important; -} - -.new-filter-card .top .name-area{ - line-height: 2; - color:white; - text-align: center; - white-space: nowrap; - -} - -@-moz-document url-prefix() { - .new-filter-card .top .name-area{ - line-height: 1.5; - color:white; - text-align: center; - - } -} -.new-filter-card .bottom{ - height:50%; - border-radius: 0px 0px 10px 10px; - border: 1px solid; - border-top:0px; - background-color:#ffffff; - -} - -.new-filter-card .bottom .name-area{ - width:80%; - overflow:hidden; - line-height: 2; - text-align: center; - - -} -.new-filter-card .bottom .name-area div { - text-overflow: ellipsis; - white-space: nowrap; - font-size: 12; -} - - -.new-filter-card .bottom .button-area{ - width:20%; -} - -.top-axis{ - min-height: 32px; - } - - -md-option[selected], md-select-menu md-option[selected]{ - color:#3b678c!important; -} - -.top-axis-container{ - width:100%; -} - - - -.tree-item-padding{ - padding-left:10px !important; -} -.tree-item-padding-leaf{ - padding-left:35px !important; -} - -.multi-hier-combo{ - min-width: 50%; -} - -@-moz-document url-prefix() { - .multi-hier-combo{ - min-width: 50%; - } -} - -.swap-axis-area{ - background-color:white!important; - width:33px; - cursor:pointer; -} - -.top-shift{ - min-width:32px; - min-height:32px; - /*margin-right:1%;*/ - padding-bottom: 5px; -} - -.filter-shift-arrow{ - margin-top:1%!important; - max-width:40px!important; -} - -.save-subObject-dialog{ - padding: 100px; -} - -.dialog-button-padding{ - padding-left: 3%; - padding-right: 3%; -} - -.filter-panel-empty{ - height:80px; - padding-left:42px; - - /* - Changed in order to center the text content inside the DIV that has not items - @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) - */ - /*padding-top:30px;*/ - display: flex; - justify-content: center; - flex-direction: column; - - width:100%; -} - -.dialog-msg{ - font-size: 10px; - color:red; -} - -.no-wrap{ - white-space:nowrap; -} - -.left-axis-shift{ - min-width:32px; - min-height:32px; - margin-bottom: 2%; -} - -.icon-color-white{ - color:white!important; -} - -.icon-color-green{ - color:green!important; -} -.menu-toolbar{ - cursor:pointer; - width: 4%; -} - -.top-axis-switch{ - width: 24px !important; - height: 24px !important; - margin: 0 !important; - padding: 0 !important; - top: 2px; -} - -.top-axis-element{ - /* height:80%; */ - margin-right:10px; - /* Empiric approach (danristo) */ - max-height:27px; -} - -.left-axis{ - height:calc(100% - 64px); -} - -.export-dialog{ - height:45%!important; - width:35%!important; -} - -.export-dialog-toolbar{ - min-height:20px; - height:15%; - padding:3% 0 0 3%; -} -.export-dialog-content{ - padding:10px; - font-size:85%; - height:60%; -} - -.side-nav-x-btn-position{ - right: 0px; - position: absolute; - top: 0px; -} - -.side-nav-tabs{ - width:33%; -} - -.filter-panel{ -/* width:100%; */ -} - -.multi-hier-dialog{ - height:25%!important; - width:25%!important; - min-width:450px; - min-height:250px; -} - -@-moz-document url-prefix() { - .multi-hier-dialog{ - height:35%!important; - width:30%!important; - min-width:450px; - min-height:250px; - } -} - - -.multi-hier-dialog .toolbar{ - min-height: 20%!important; - padding-top: 10px; - padding-left: 10px; -} - -.multi-hier-dialog .toolbar .x-btn{ - right: 0px; - position: absolute; - top: 0px; -} - -.multi-hier-dialog .content{ - padding:10px; - font-size:85% -} - -.multi-hier-dialog .content .mh-input{ - width:50%; - padding-left:10% -} - -.multi-hier-dialog .action-btn{ - line-height:25px; -} - -.max-height{ - height:100%!important; -} - -.delete-version-info{ - width:10%; - text-align: center; - font-weight:bold; - text-transform: uppercase; - border-left: 0.5px solid black; -} - -.delete-version-info{ - width:40%; - text-align: center; - font-weight:bold; - text-transform: uppercase; - border-left: 0.5px solid black; -} - -.delete-version-id{ - width:10%; - text-align: center; - border-left: 0.5px solid black; -} - -.delete-version{ - width:40%; - text-align: center; - border-left: 0.5px solid black; - font-size: 66% -} - -.what-if-msg{ - font-size: 70%; - padding-left: 10px; -} - -.leaf-paddin-filter{ - padding-left: 60px; -} - -.filter-dialog-dimensions { - min-width:350px; - width: 80%; - height: 60%; -} - -.designer-buttons-dialog-content { - overflow:hidden; -} - -.designer-buttons-dialog-angular-table-height { - height:60%; -} - -.scenario-secondary-toolbar { - background-color: #A9C3DB !important; - min-height: 40px; - height: 40px; - padding-left: 10px; - padding-top: 6px; -} - -.designer-cube-dialog { - min-height: 40px; - height: 40px; -} - -.swith-position-arrow-vertical{ - min-width: inherit !important; - width: inherit !important; -} - diff --git a/knowagewhatifengine/src/main/webapp/css/whatIf.css b/knowagewhatifengine/src/main/webapp/css/whatIf.css deleted file mode 100644 index 8e27db34dfc..00000000000 --- a/knowagewhatifengine/src/main/webapp/css/whatIf.css +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Knowage, Open Source Business Intelligence suite - * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * - * Knowage is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Knowage 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - - -/******************************************************************************************************* - * Actions - ********************************************************************************************************/ -/********************************************************************************************************/ - -.pivot-table{ - /*border-collapse: collapse;*/ - position:absolute; - text-align:left; - table-layout: fixed; - color: rgba(0,0,0,0.54); - font-size:12px; -/* padding:5px; */ -} - -.pivot-table thead{ - overflow:auto; -} - -/*.pivot-table th{ - position: relative !important; - /*border-top-width: 1px !important;*/ - /*border-right-width: 1px !important; - border-bottom: 1px solid #3b678c; - border-right: 1px solid #3b678c; - - padding:5px; - font-family: Verdana; - background: #f5f5f5; - white-space: nowrap; -} -*/ -.pivot-table th { - position: relative !important; - /*border-top-width: 1px !important;*/ - /*border-right-width: 1px !important;*/ - border-bottom: 1px solid #3b678c; - border-right: 1px solid #3b678c; - - padding:5px; - font-family: Verdana; - background: #f5f5f5; - white-space: nowrap; - text-align: left; -} - -.pivot-table td{ - border-top-width: 1px !important; - border-right-width: 1px !important; - text-align: right; - vertical-align: middle; - /*border-top-color: #d0d0d0;*/ - font-family: Verdana; - border-bottom: 1px solid #3b678c; - border-right: 1px solid #3b678c; - max-height: 43px !important;; -} - -.pivot-table tr:nth-child(even) { - background-color: #f1f1f1; -} -.pivot-table tr:nth-child(odd) { - background-color: #ffffff; -} - -.pivot-table-selected { - - - border: 2px solid #ff0080 !important; - color: rgba(0,0,0,0.54); - font-size:12px; - - font-family: Verdana; - background: #f5f5f5; - position: relative !important; - -ms-user-select: none; - user-select: none; - -} - - - - /*******************************************************************************************************/ - - - -.rotate span { - height: auto !important; - -moz-transform: rotate(90.0deg); /* FF3.5+ */ - -o-transform: rotate(90.0deg); /* Opera 10.5 */ - -webkit-transform: rotate(90.0deg); /* Saf3.1+, Chrome */ - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0.917); - /* IE6,IE7 */ - -ms-filter: - "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.917)"; - /* IE8 */ -} - -.x-pressed-drill.drill-btn-left, -.x-pressed-drill.drill-btn-center, -.x-pressed-drill.drill-btn-right{ - background-color: #d0d0d0 !important; -} - -.drill-btn-left{ - border: none !important; - margin: 0px !important; - margin-right: -2px !important; - right: 2px !important; - border-radius: 0px !important; - background-color: #e3e4e6 !important; -} -.drill-btn-center{ - border: none !important; - margin: 0px !important; - border-radius: 0px !important; - border-left: 1px solid #d0d0d0 !important; - border-right: 1px solid #d0d0d0 !important; - background-color: #e3e4e6 !important; -} -.drill-btn-right { - border: none !important; - margin: 0px !important; - margin-left: -2px !important; - left: 2px !important; - border-radius: 0px !important; - background-color: #e3e4e6 !important; -} -.swap-column-panel { - background-image: url(../img/swap-column-panel2.png); - background-position: center center; - background-repeat: no-repeat; - margin: 2px; -} - -.swap-row-panel { - background-image: url(../img/swap-row-panel.png); - background-position: center center; - background-repeat: no-repeat; - margin: 2px; -} - - - -/*------------------*/ -/*expandable members*/ -/*------------------*/ - -.expanded{ - vertical-align:middle; - text-align: left; - background-color: -webkit-linear-gradient(top,#f9f9f9,#e3e4e6); -} -.collapsed{ - vertical-align:middle; - text-align: left; - background-color: -webkit-linear-gradient(top,#f9f9f9,#e3e4e6); -} -.expanded img, -.collapsed img{ - position: relative; - left: 0px; - text-align: left; - vertical-align: top; - padding: 3px; -} -td:focus { - outline:none; - border: 1px solid #ff0080 !important; - cursor: text; -} - -.odd-row td{ - background-color: #F6F6F7 !important; -} -.even-row td{ - background-color: white !important; - -} - -.odd-column{ - background-color: transparent; -} -.even-column{ - background-color: transparent; -} - -.x-pivot-table thead tr:first-child { - - background-color: #FFF; -} - -.dimension-title{ - border-top: 1px solid #D0D0D0; - border-right: 1px solid #D0D0D0; - font: bold 11px/13px tahoma,arial,verdana,sans-serif; - text-align: left; - padding-left: 5px; - padding-right: 5px; - vertical-align: middle; -} -.dimension-title img{ - position: relative; - left: 0px; - text-align: left; - vertical-align: middle; - padding: 3px; -} -.swapaxes { - background-image: url(../img/double-arrow.png); - background-color: transparent !important; - background-repeat: no-repeat; - background-position: center center; -} - -/*------------------*/ -/* filter panel*/ -/*------------------*/ -.filter-title { - background-color: transparent; - border-top: 0px !important; - border-left: 0px !important; - border-right: 0px !important; - padding: 4px; - text-align: center; -} - -.filter-value { - font-style:italic; - background-color: transparent; - padding: 4px; - text-align: center; -} - -.filter-funnel-image { - background-image: url(../img/filter_3.png); - background-position: center center; - background-repeat: no-repeat; - width: "90%"; - height: "90%"; -} - -.filter-funnel-body{ - background-color: transparent; - border-top: 0px !important; - border-bottom: 0px !important; - border-right: 0px !important; - padding: 4px; -} - -.filter-column { - background-image: url(../img/filter_10.png); - background-color: transparent; - border-top: 0px !important; - border-bottom: 0px !important; - border-right: 0px !important; - margin-left: 4px; - background-position: center center; - background-repeat: no-repeat; - text-align: center; -} - -.filter-row { - background-image: url(../img/filter_10.png); - background-color: transparent; - border-bottom: 0px !important; - border-right: 0px !important; - border-left: 0px !important; - margin-top: 4px; - padding-top: 10px; - text-align: center; - background-position: center center; - background-repeat: no-repeat; -} - -/*------------------*/ -/* toolbar */ -/*------------------*/ -/* .drill-mode{ - background-image: url(../img/drill.png); -} */ -.BUTTON_MDX{ - background-image: url(../img/mdx.png); -} -.BUTTON_EDIT_MDX{ - background-image: url(../img/edit_mdx.png); -} -.BUTTON_UNDO{ - background-image: url(../img/undo.png); -} -.BUTTON_FATHER_MEMBERS{ - background-image: url(../img/show_parent_members.png); -} -.BUTTON_HIDE_SPANS{ - background-image: url(../img/hide_spans.png); -} -.BUTTON_SHOW_PROPERTIES{ - background-image: url(../img/show_props.png); -} -.BUTTON_SHOW_COMPACT_PROPERTIES{ - background-image: url(../img/show_compact_props.png); -} - -.BUTTON_HIDE_EMPTY{ - background-image: url(../img/empty_rows.png); -} -.BUTTON_SAVE{ - background-image: url(../img/save16.png); -} -.BUTTON_SAVE_NEW{ - background-image: url(../img/save-version16.png); -} -.BUTTON_FLUSH_CACHE{ - background-image: url(../img/reload16.png); -} -.lock-icon{ - background-image: url(../img/locked_green.png); -} -.unlock-icon{ - background-image: url(../img/unlocked_green.png); -} -.lock-other-icon{ - background-image: url(../img/locked_other_green.png); -} -.BUTTON_VERSION_MANAGER{ - background-image: url(../img/delete-versions16.png); -} -.BUTTON_EXPORT_OUTPUT{ - background-image: url(../img/toolbar-export.png); -} -.context-menu-icon{ - background-image: url(../img/menu16.png); -} -.BUTTON_CALCULATED_MEMBERS{ -background-image: url(../img/cubesmall.png); -} -.BUTTON_EXPORT_XLS{ -background-image: url(../img/xls16.png); -} - -/*------------------*/ -/* Multi hierarchy */ -/*------------------*/ -.multihierarchy-font{ - font-size: 11 !important; -} - - -.multi-hierarchy { - background-image: url(../img/multi_hierarchy_2.png); - background-position: left; - background-repeat: no-repeat; - background-size: 12px 12px; -} - -/*------------------*/ -/* headers */ -/*------------------*/ -.internal-row-header { - margin-top: 1px !important; -} - -.internal-column-header { - margin-left: 1px !important; -} - diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterCard.html b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterCard.html index 288b0fceb39..93f7e006750 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterCard.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterCard.html @@ -1,31 +1,24 @@ -
- -
-
- - - -
-
{{filter.caption}}
-
- -
-
-
{{FiltersService.getSlicerNamesString(filter.selectedHierarchyUniqueName)}}
-
+ ng-repeat="filter in filterCardList|limitTo:numVisibleFilters:index" + ng-drag="true" ng-drag-data="filter" + ng-drag-success="dragSuccess('filter',$index)" + id="filter-{{filter.name}}" + layout="row"> -
- - - -
-
+ + + + + {{filter.caption}} + {{translate.load('sbi.olap.drag.filter')}} + + + + {{FiltersService.getSlicerNamesString(filter.selectedHierarchyUniqueName)}} + +
+ + {{translate.load('sbi.olap.drop.filter')}}
\ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterDialog.html b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterDialog.html index f395ef3c77b..2ae09e0ddc7 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterDialog.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterDialog.html @@ -1,82 +1,74 @@ - + - - - {{filterDialogToolbarName}} - - + +
+

{{filterDialogToolbarName}}

+
- + You need at least {{minNumOfLetters}} letters to start search! -
-
+
+ + + {{translate.load("sbi.common.unselect.all");}} + + {{::translate.load("sbi.common.unselect.all");}} + + + {{::translate.load('sbi.olap.filter.showselected')}} + -
- - - {{translate.load("sbi.common.unselect.all");}} - - {{translate.load("sbi.common.unselect.all");}} - - - Show selected only - - - - Show All - -
- -
+ + {{::translate.load('sbi.olap.filter.showall')}} + - - - - - - + + + + - - - + + {{::translate.load('sbi.generic.search')}} + + - - + {{showSiblings?'Show siblings':'Hide siblings'}} - - - + +
+
+
{{::translate.load('sbi.olap.filter.lockedhierarchies')}}
-
-
    - -
-
- +
+
    + +
+
+ - +
- + - + Cancel - + Save diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterPanel.html b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterPanel.html index 3a203c6825a..a2b6b4d429f 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterPanel.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/filter/filterPanel.html @@ -1,18 +1,17 @@ -
+
-
- {{filterPanelEmpty}} +
+
{{filterPanelEmpty}}
+ aria-label="shift to left" ng-click="filterShift('left', index, filterCardList, numVisibleFilters)" + ng-if="filterCardList.length > numVisibleFilters && indexChangingSer.hasPrevious(index)"> - diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/filter/multiHierarchyDialog.html b/knowagewhatifengine/src/main/webapp/html/template/main/filter/multiHierarchyDialog.html index fb47cc3cd17..9eb60c01aa1 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/filter/multiHierarchyDialog.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/filter/multiHierarchyDialog.html @@ -1,25 +1,20 @@ - + - -
+ +
{{member.caption}} - - - -
- - - The selected hierarchy is {{member.hierarchies[member.selectedHierarchyPosition].caption}}. - You can change it acting on the form below. - -
- - + +

+ The selected hierarchy is {{member.hierarchies[member.selectedHierarchyPosition].caption}}. + You can change it acting on the form below. +

+

Available hierarchies:

+ @@ -27,10 +22,10 @@
- + Cancel - + Save diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/filter/treeDeeperLevels.html b/knowagewhatifengine/src/main/webapp/html/template/main/filter/treeDeeperLevels.html index 95068236581..50fb728a263 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/filter/treeDeeperLevels.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/filter/treeDeeperLevels.html @@ -1,7 +1,7 @@
  • -
    +
    - + {{item.name}} diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/olap/crossNavigationMenu.html b/knowagewhatifengine/src/main/webapp/html/template/main/olap/crossNavigationMenu.html index 133bd75f225..a9f440c47db 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/olap/crossNavigationMenu.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/olap/crossNavigationMenu.html @@ -1,11 +1,12 @@ - - -

    Cross Navigation

    + +
    +

    Cross Navigation

    +
    - - + + {{ target.title }}

    {{ target.description }}

    - + - - OK - Cancel + + OK + diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/olap/leftToolbarPlusMain.html b/knowagewhatifengine/src/main/webapp/html/template/main/olap/leftToolbarPlusMain.html index 1c8a144f77a..cd3dbb9563c 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/olap/leftToolbarPlusMain.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/olap/leftToolbarPlusMain.html @@ -1,13 +1,13 @@
    -
    - +
    +
    -
    +
    +
    {{translate.load('sbi.olap.drop.dimension')}}
    -
    +
    + ng-click="dimensionShift('up')">
    @@ -73,18 +73,6 @@ >
    - - - - - - - - - - - -
    diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapDesigner.html b/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapDesigner.html index 7451c31ba4c..8bb44e34a89 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapDesigner.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapDesigner.html @@ -1,106 +1,85 @@
    - - -
    -

    Olap Designer

    -
    - - Start - Back - - - - -
    - - - -
    -
    - - - {{l.name}} - - -
    -
    - -
    - -
    -
    - - - {{l.name}} - - -
    - - -
    - -
    -
    - - - {{l}} - - -
    -
    - -
    -
    - -
    -
    - - - - -
    -
    - -
    - XMLA Parameters - - -
    - -
    - - - - - - - - - -
    - -
    - -
    -
    -
    - - - -
    - -
    - - - + +
    +

    Olap Designer

    + + Back + Start +
    +
    + + + +
    +
    + + + + {{l.name}} + + +
    +
    + +
    + +
    +
    + + + + {{l.name}} + + +
    +
    + +
    +
    + + + + {{l}} + + +
    +
    + +
    +
    + +
    +
    + + + + +
    +
    + +
    + XMLA Parameters + + +
    + +
    + + + + + + + + + +
    + +
    + +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapPanel.html b/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapPanel.html index 4f1f8228423..c888455fbb0 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapPanel.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/olap/olapPanel.html @@ -3,6 +3,5 @@ -
    diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/olap/topToolbar.html b/knowagewhatifengine/src/main/webapp/html/template/main/olap/topToolbar.html index bae4667e8bd..b05b35c1890 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/olap/topToolbar.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/olap/topToolbar.html @@ -4,55 +4,51 @@   - + -
    - +
    + -
    +
    -
    -
    +
    +
    - - - + + + -
    - {{cutName(column.caption, 0, column.hierarchies.length > 1)}} -
    +
    + {{cutName(column.caption, 0, column.hierarchies.length > 1)}} +
    -
    - - - +
    + + + +
    +
    +
    + + + +
    +
    {{translate.load('sbi.olap.drop.dimension')}}
    -
    - - + +
    + +
    -
    -
    -
    - - +
    +
    + +
    - - - -
    - - - - - - -
    - - +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/savesubobject/saving_subobject_dialog.html b/knowagewhatifengine/src/main/webapp/html/template/main/savesubobject/saving_subobject_dialog.html index 91a9a6eb70c..133d285daa2 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/savesubobject/saving_subobject_dialog.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/savesubobject/saving_subobject_dialog.html @@ -1,45 +1,42 @@ - -

    Saving customized view

    + +
    +

    Saving customized view

    +
    - - -
    + +
    - - -
    -
    {{translate.load("sbi.olap.generic.required");}}
    -
    + + +
    +
    {{translate.load("sbi.olap.generic.required");}}
    +
    -
    - -
    + - - + + -
    -
    + - - - - Public - Private - + + + Public + Private + -
    - - - {{translate.load("sbi.common.cancel");}} - - - {{translate.load("sbi.common.ok");}} - - +
    + + + {{translate.load("sbi.common.cancel");}} + + + {{translate.load("sbi.common.ok");}} + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/drillThrough.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/drillThrough.html index 8c9ed9d318c..f929a43c3e6 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/drillThrough.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/drillThrough.html @@ -1,67 +1,52 @@ - - - -

    Drill Through

    + +
    +

    Drill Through

    +
    - - - - Select visible levels: - -
    -
    - - - - - - - {{ child.caption }} - - - - - -
    - - - - {{translate.load("sbi.olap.drillTrough.clearAll")}} - -
    -
    - - - - - - - - + + + Select visible levels: +
    + + + + + + + {{ child.caption }} + + + + + + + + + {{translate.load("sbi.olap.drillTrough.clearAll")}} + +
    +
    + + + +
    + - -
    -
    - - - + - + 0 10 25 @@ -70,21 +55,20 @@

    Drill Through

    250 500 1000 -
    -
    - - - - - Cancel - - - Export - - - Apply - -
    - - + + + + + + + Cancel + + + Export + + + Apply + + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/saveAsNew.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/saveAsNew.html index e753baca9a8..e1e9a4c03b6 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/saveAsNew.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/saveAsNew.html @@ -1,9 +1,11 @@ - -

    {{translate.load("sbi.olap.toolbar.export.wizard.title")}}

    + +
    +

    {{translate.load("sbi.olap.toolbar.export.wizard.title")}}

    +
    - + {{translate.load("sbi.olap.toolbar.save.as.description")}}
    @@ -12,14 +14,15 @@ - - - Save - - - Cancel - -
    + + + Cancel + + + Save + + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sendMdx.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sendMdx.html index 01b707bced1..f60c263bd19 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sendMdx.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sendMdx.html @@ -1,25 +1,25 @@ - + - -

    Insert MDX Query

    + +
    +

    Insert MDX Query

    +
    - + - - - + - - Cancel - - - Save - - + + Cancel + + + Save + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/showMdx.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/showMdx.html index 17fe8681c68..1e730a62174 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/showMdx.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/showMdx.html @@ -1,16 +1,18 @@ - -

    Current MDX Query

    + +
    +

    Current MDX Query

    +
    - -
    -
    + +
    
    +	
    - + Close diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sortingSettings.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sortingSettings.html index 71d18ff4949..9384df42d1f 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sortingSettings.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/sortingSettings.html @@ -1,22 +1,26 @@ - + - -

    Sorting settings

    + +
    +

    Sorting settings

    +
    - - - - {{d.label}} - - - - - - - Save - - - + +
    + + + {{d.label}} + + + +
    +
    + + + + Save + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/writeBackCell.html b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/writeBackCell.html index 291a3e2a4c7..ae92185e405 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/writeBackCell.html +++ b/knowagewhatifengine/src/main/webapp/html/template/main/toolbar/writeBackCell.html @@ -1,22 +1,22 @@ - - + - -

    Set Value Formula

    + +
    +

    Set Value Formula

    +
    - + + + - - - Save - - - Cancel - - - - + + Cancel + + + Save + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS1.html b/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS1.html index 30904990d02..6b959f410f7 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS1.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS1.html @@ -1,55 +1,46 @@ - - - -

    Cross Navigation Definition

    - - Add New -
    - - -
    - - - - - -
    -

    Select the type of cross navigation below

    -
    -
    - - - {{t.name}} - - -
    -
    - + +
    +

    Cross Navigation Definition

    + + Add New +
    +
    -
    + + + +
    +

    Select the type of cross navigation below

    +
    +
    + + + + {{t.name}} + + +
    +
    +
    - - Next - - + Cancel + + Next +
    diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS2.html b/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS2.html index 9498e874727..003c509df4a 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS2.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/edit/crossNavWizardS2.html @@ -1,77 +1,72 @@ - - + - -

    Cross Navigation Definition

    + +
    +

    Cross Navigation Definition

    +
    - - -
    -

    - The parameters for cross navigation on cell required the name of the dimension, hierarchy and level. -In order to select these values you should click on "select from table". Than on the table you should open the filter panel of the hierarchy you want to include in the parameter. Than on the filter panel you should select one member of the level you want to include in the cross navigation. -For example: suppose you want to create a parameter on dimension="Product" hierarchy="[Product]" level="[Product].[Product Department]. You should select the hierarchy Product on dimension Product. Than you should open the filter panel and select a member of the level [Product].[Product Department] for example Food.Seafood - -

    + +
    +

    + The parameters for cross navigation on cell required the name of the dimension, hierarchy and level. + In order to select these values you should click on "select from table". Than on the table you should open the filter panel of the hierarchy you want to include in the parameter. Than on the filter panel you should select one member of the level you want to include in the cross navigation. + For example: suppose you want to create a parameter on dimension="Product" hierarchy="[Product]" level="[Product].[Product Department]. You should select the hierarchy Product on dimension Product. Than you should open the filter panel and select a member of the level [Product].[Product Department] for example Food.Seafood +

    -
    -
    - - - - -
    - - Select from table - +
    +
    + + + + +
    + + Select from table + +
    + +
    +
    + + + + +
    +
    + +
    +
    + + + + +
    -
    + + Select from table + +
    - - -
    -
    - - - - -
    -
    - - +
    +
    + + + + +
    +
    -
    -
    - - - - -
    - - - Select from table - -
    +
    +
    -
    -
    - - - - -
    -
    - -
    -
    - - Finish - - - Cancel - + + Cancel + + + Finish +
    diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerButtonsWizard.html b/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerButtonsWizard.html index 42ab0e055fd..3f5fc08fbb8 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerButtonsWizard.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerButtonsWizard.html @@ -1,21 +1,19 @@ -
    - -

    Buttons Wizard

    -
    + +
    +

    Buttons Wizard

    +
    +
    - - + + Un-Select All Visible - - - - + @@ -23,29 +21,27 @@

    Buttons Wizard

    - + + scope-functions="tableFunction">
    - - Save - - - Cancel - + + Cancel + + + Save + -
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerToolbar.html b/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerToolbar.html index a4af2f0d538..c2ac13a954f 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerToolbar.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/edit/olapDesignerToolbar.html @@ -1,35 +1,25 @@
    - - - - - - - - {{translate.load(odb.name)}} - - - - - -
    - - - {{translate.load("sbi.olap.designer.close")}} - - - - {{translate.load("sbi.olap.designer.save")}} - + + + + + + + {{translate.load(odb.name)}} + + + + + - - - - - -
    +
    + + {{translate.load("sbi.olap.designer.close")}} + + + + {{translate.load("sbi.olap.designer.save")}} + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/edit/pagination_wizard.html b/knowagewhatifengine/src/main/webapp/html/template/right/edit/pagination_wizard.html index 6a0ae4b5081..672c62f69b5 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/edit/pagination_wizard.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/edit/pagination_wizard.html @@ -1,28 +1,23 @@ -
    - -

    Pagination Wizard

    -
    + +
    +

    Pagination Wizard

    +
    +
    - - -
    - - Use table pagination - -
    - - - -
    + + + Use table pagination + + - - - Save - - - Cancel - - -
    + + + + Cancel + + + Save + +
    \ No newline at end of file diff --git a/knowagewhatifengine/src/main/webapp/html/template/right/sideNavigation.html b/knowagewhatifengine/src/main/webapp/html/template/right/sideNavigation.html index 09ae12d7104..76a6030bcf6 100644 --- a/knowagewhatifengine/src/main/webapp/html/template/right/sideNavigation.html +++ b/knowagewhatifengine/src/main/webapp/html/template/right/sideNavigation.html @@ -1,46 +1,38 @@ -
    - - - - - - Menu - - - - - -
    -
    - - - -
    -
    - - - -
    -
    - - - - -
    +
    + + +
    +

    Settings

    + + + + +
    +
    +
    +
    + + + +
    +
    + + + +
    +
    + + + + +
    +
    + +
    +

    Settings

    +
    +
    + + +
    -Menu - - - diff --git a/knowagewhatifengine/src/main/webapp/img/double-arrow.png b/knowagewhatifengine/src/main/webapp/img/double-arrow.png deleted file mode 100644 index a2aa331dee0..00000000000 Binary files a/knowagewhatifengine/src/main/webapp/img/double-arrow.png and /dev/null differ diff --git a/knowagewhatifengine/src/main/webapp/img/menu16.png b/knowagewhatifengine/src/main/webapp/img/menu16.png deleted file mode 100644 index bbfc282ad5b..00000000000 Binary files a/knowagewhatifengine/src/main/webapp/img/menu16.png and /dev/null differ diff --git a/knowagewhatifengine/src/main/webapp/img/xls16.png b/knowagewhatifengine/src/main/webapp/img/xls16.png deleted file mode 100644 index 046040add8a..00000000000 Binary files a/knowagewhatifengine/src/main/webapp/img/xls16.png and /dev/null differ diff --git a/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages.properties b/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages.properties index f3b2abe13b5..2ac3706680c 100644 --- a/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages.properties +++ b/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages.properties @@ -46,6 +46,7 @@ sbi.common.wait = Please wait... sbi.common.wait.long = This operation can take some minutes. Please wait... sbi.common.warning = Warning sbi.generic.error = An error occurred +sbi.generic.search = Search sbi.generic.sessionexp = Session expired sbi.olap.ad.error = An error occurred while loading analytical drivers sbi.olap.algorithmsLoad.error = An error occurred while loading algorithms @@ -74,6 +75,9 @@ sbi.olap.designer.templateSave = XML template successfully created sbi.olap.drillDown.error = An error occurred by drill down functionality sbi.olap.drillTrough.clearAll = Clear All sbi.olap.drillUp.error = An error occurred by drill up functionality +sbi.olap.drag.filter = Drag one of the slicer to the toolbar below +sbi.olap.drop.filter = Drop here to use as a slicer +sbi.olap.drop.dimension = Drop here to use as a dimension sbi.olap.dt.error = Error in drill through sbi.olap.dt.warning = If the drill though is executed on a cell with an high level of aggregation, this operation can take long time . In the meanwhile you can continue with your work sbi.olap.dtLevels.error = An error occurred while getting drill through levels @@ -97,6 +101,9 @@ sbi.olap.execution.table.filter.no.measure = A measure can not be used as a filt sbi.olap.filtering.info = Filtering... sbi.olap.filtering.no.selected.members = You need to select at least one member sbi.olap.filterSearch.error = An error occurred during search for filter +sbi.olap.filter.lockedhierarchies = There are no children in this selection. Click on "show all" to display all items. +sbi.olap.filter.showall = show all +sbi.olap.filter.showselected = show selected only sbi.olap.generic.required = required sbi.olap.help.title = Help sbi.olap.hierarchy.error = An error occurred while updating hierarchy. diff --git a/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages_it_IT.properties b/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages_it_IT.properties index c27ee3acf21..ccd66fd3af1 100644 --- a/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages_it_IT.properties +++ b/knowagewhatifengine/src/main/webapp/js/spagobi/messages/messages_it_IT.properties @@ -42,6 +42,7 @@ sbi.common.wait=Attendere prego... sbi.common.wait.long=Attendere prego.. Questa operazione potrebbe richiedere qualche minuto... sbi.common.warning=Attenzione sbi.generic.error=Errore +sbi.generic.search=Cerca sbi.generic.sessionexp=Sessione scaduta sbi.olap.ad.error=Errore durante il caricamento dei driver analitici sbi.olap.algorithmsLoad.error=Errore durante il caricamento degli algoritmi @@ -93,6 +94,8 @@ sbi.olap.execution.table.filter.no.measure=Non è possibile mettere le misure tr sbi.olap.filtering.info=Filtrando... sbi.olap.filtering.no.selected.members=Devi selezionare almeno un elemento sbi.olap.filterSearch.error=Errore durante la ricerca di un filtro +sbi.olap.filter.showall=mostra tutti +sbi.olap.filter.showselected=mostra selezionati sbi.olap.generic.required=Richiesto sbi.olap.help.title=Help sbi.olap.hierarchy.error=Errore durante l'aggiornamento della gerarchia. diff --git a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/controllers/mainController.js b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/controllers/mainController.js index e475c0176ca..aaf29220e23 100644 --- a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/controllers/mainController.js +++ b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/controllers/mainController.js @@ -24,6 +24,10 @@ olapMod.config(['$mdThemingProvider', function($mdThemingProvider) { $mdThemingProvider.setDefaultTheme('knowage'); }]); +olapMod.config(['$locationProvider', function($locationProvider) { + $locationProvider.html5Mode({ enabled: true, requireBase: false }); }] +) + olapMod.controller("olapController", [ "$scope", '$rootScope',"$timeout", "$window", "$mdDialog", "$http", '$sce', '$mdToast', '$mdSidenav', 'sbiModule_config', 'sbiModule_messaging', 'sbiModule_restServices', 'sbiModule_translate','sbiModule_docInfo', diff --git a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/FilterPanel.js b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/FilterPanel.js index 4ae24191aa8..7c020cc19fe 100644 --- a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/FilterPanel.js +++ b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/FilterPanel.js @@ -110,7 +110,7 @@ function filterPanelController($scope, $timeout, $window, $mdDialog, $http, $sce $scope.hierarchyTreeService = hierarchyTreeService; $scope.FiltersService = FiltersService; var cutArray = [12, 11, 10, 9, 6]; //array with maximum lengths for card - $scope.selectView = true; + $scope.selectView = false; @@ -255,6 +255,10 @@ function filterPanelController($scope, $timeout, $window, $mdDialog, $http, $sce $scope.expandTreeAsync = function(item){ if($scope.selectView ){ + $scope.showTreeError = true; + $timeout(function(){ + $scope.showTreeError = false; + },10000) item.collapsed = true; return; } diff --git a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/OlapDesigner.js b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/OlapDesigner.js index 5a8731562fe..76cd61c8f95 100644 --- a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/OlapDesigner.js +++ b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/directives/components/OlapDesigner.js @@ -30,7 +30,7 @@ angular.module('olap_designer', ['sbiModule']) }); -function olapDesignerController($scope, channelMessaging, $timeout, $window, $mdDialog, $http, $sce, +function olapDesignerController($scope, channelMessaging, $timeout, $window, $location, $mdDialog, $http, $sce, sbiModule_messaging, sbiModule_restServices, sbiModule_translate, toastr, $cookies, sbiModule_docInfo, sbiModule_config) { @@ -135,8 +135,12 @@ $scope.saveMDX = function(){ sbiModule_restServices.promisePost("1.0/designer/cubes?SBI_EXECUTION_ID=" + JSsbiExecutionID,"",angular.toJson($scope.template)) .then(function(response) { + var context = $location.search().SBICONTEXT; + var url = sbiModule_config.contextName + "/restful-services/pages/execute?SBI_EXECUTION_ID=" - + JSsbiExecutionID+"&mode="+mode+"&schemaID="+$scope.selectedSchema.id+"&cubeName="+$scope.selectedCube.name+"&schemaName="+$scope.selectedSchema.name+"&ENGINE="+engineName+"¤tContentId="+$scope.selectedSchema.currentContentId; + + JSsbiExecutionID+"&mode="+mode+"&schemaID="+$scope.selectedSchema.id+"&cubeName="+$scope.selectedCube.name+"&schemaName=" + +$scope.selectedSchema.name+"&ENGINE="+engineName+"¤tContentId="+$scope.selectedSchema.currentContentId+ + '&SBICONTEXT='+context; $window.location = url; diff --git a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/services/FiltersService.js b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/services/FiltersService.js index 2a7cd61a0d5..45ab4ff2a8a 100644 --- a/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/services/FiltersService.js +++ b/knowagewhatifengine/src/main/webapp/js/src/angular_1.x/scripts/services/FiltersService.js @@ -61,7 +61,7 @@ } this.getSlicers = function(hierachyUniqueName){ - return this.getHierarchyByUniqueName(hierachyUniqueName).slicers; + return (this.getHierarchyByUniqueName(hierachyUniqueName) ? this.getHierarchyByUniqueName(hierachyUniqueName).slicers : []); } this.isSlicer = function(hierachyUniqueName,memberUniqueName){ diff --git a/logo/logo.png b/logo/logo.png new file mode 100644 index 00000000000..34fbe678453 Binary files /dev/null and b/logo/logo.png differ diff --git a/logo/logo.svg b/logo/logo.svg new file mode 100644 index 00000000000..aab220c568f --- /dev/null +++ b/logo/logo.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/logo/logo_black.png b/logo/logo_black.png new file mode 100644 index 00000000000..ad4d3ea300b Binary files /dev/null and b/logo/logo_black.png differ diff --git a/logo/logo_black.svg b/logo/logo_black.svg new file mode 100644 index 00000000000..1519be89976 --- /dev/null +++ b/logo/logo_black.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + diff --git a/publiccode.yml b/publiccode.yml index 80e05eef207..c7ff6af4e1f 100644 --- a/publiccode.yml +++ b/publiccode.yml @@ -15,22 +15,6 @@ dependsOn: version: '8' versionMax: '' versionMin: '' - - name: MySQL - optional: true - version: '5.7' - versionMax: '' - versionMin: '' - - name: PostgreSQL - optional: true - version: '9' - versionMax: '' - versionMin: '' - proprietary: - - name: Oracle - optional: true - version: '11,12' - versionMax: '' - versionMin: '' description: it: apiDocumentation: 'https://knowage.docs.apiary.io/' @@ -38,33 +22,51 @@ description: - OW2CON '18 Best Project - Market award documentation: 'https://knowage-suite.readthedocs.io/' features: - - Enterprise Reporting per la produzione e distribuzione di report statici - >- - Big Data per unire i dati strutturati aziendali con quelli esterni multi + La suite è composta da diversi moduli, ognuno concepito per uno + specifico dominio analitico + - >- + Sono utilizzabili singolarmente o combinati garantendo maggior copertura + dei requisiti dell'utente + - >- + BIG DATA per unire i dati strutturati aziendali con quelli esterni multi strutturati - >- - Location Intelligence per unire business data con informazioni inerenti - allo spazio o geografiche + SMART INTELLIGENCE per la tipica BI su dati strutturati, incentrata su + selfservice/ad-hoc reporting + - ENTERPRISE REPORTING per la produzione e distribuzione di report statici - >- - Performance Management per gestire i KPI e organizzare scorecard, per il - monitoraggio in real-time + LOCATION INTELLIGENCE per unire business data con informazioni + geografiche o spaziali - >- - Predictive Analysis per analisi avanzate, ad esempio previsionali o - prescrittive + PERFORMANCE MANAGEMENT per gestire i KPI e organizzare scorecards, per + il monitoraggio in realtime - >- - Smart Intelligence per la tipica BI su dati strutturati, incentrata su - self-service/ad-hoc reporting + PREDICTIVE ANALYSIS per analisi avanzate, ad esempio previsionali o + prescrittive genericName: Business Analytics suite longDescription: > - Knowage è la suite open source completa per la moderna Business Analytics - su fonti dati tradizionali e sistemi big data. Le sue funzionalità, come - la federazione, il mash-up, il data/text mining e la visualizzazione - avanzata dei dati, offrono un supporto completo per un'analisi ricca in - grado di combinare informazioni provenienti da diverse fonti. La suite è - composta da diversi moduli, ognuno concepito per uno specifico dominio - analitico. Possono essere utilizzati singolarmente come soluzione completa - per un determinato compito o combinati tra loro per garantire la piena - copertura dei requisiti dell'utente. + Knowage è la suite open source per la business analytics moderna che + affianca alle tradizionali capacità di business intelligence, strumenti + agili che promuovono l’autonomia degli utenti business e funzionalità + avanzate rivolte al segmento emergente dei data scientist. E’ quindi un + prodotto per la piena valorizzazione del patrimonio dati aziendale, anche + in relazione a sorgenti informative esterne ed eterogenee, cogliendo in + pieno il significato del fenomeno dei big data. La suite Knowage è + supportata dal Gruppo Engineering, uno dei principali players nel campo + della digital transformation per il settore pubblico e privato, con oltre + 12.000 professionisti e 65 sedi nel mondo. + screenshots: + - >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/screenshots/knowage-covid-italy-regional.png + - >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/screenshots/knowage-cockpit2.jpg + - >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/screenshots/knowage-cockpit.jpg + - >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/screenshots/knowage-map.jpg + - >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/screenshots/knowage-responsive2.jpg shortDescription: Suite open source completa per la moderna Business Analytics videos: - 'https://www.youtube.com/watch?v=-fZIsVh_qsc' @@ -96,7 +98,7 @@ it: conforme: gdpr: false lineeGuidaDesign: false - misureMinimeSicurezza: true + misureMinimeSicurezza: false modelloInteroperabilita: false countryExtensionVersion: '0.2' piattaforme: @@ -116,6 +118,8 @@ localisation: - fr - es localisationReady: true +logo: >- + https://raw.githubusercontent.com/KnowageLabs/Knowage-Server/master/logo/logo.svg maintenance: contacts: - email: angelo.bernabei@eng.it @@ -123,12 +127,9 @@ maintenance: - email: davide.zerbetto@eng.it name: Davide Zerbetto contractors: - - name: ENAV S.p.A. - until: '2020-12-31' - website: 'https://www.enav.it/sites/public/it/Home.html' - - name: Azienda Unità Sanitaria Locale di Modena - until: '2020-12-31' - website: 'http://www.ausl.mo.it/home' + - name: Engineering Ingegneria Informatica S.p.A. + until: '2050-12-31' + website: 'https://www.eng.it/' type: contract name: Knowage Server platforms: @@ -136,10 +137,12 @@ platforms: - windows - mac - linux -releaseDate: '2020-02-24' +releaseDate: '2020-03-24' roadmap: 'https://github.com/KnowageLabs/Knowage-Server/blob/master/ROADMAP.md' softwareType: standalone/web -softwareVersion: 7.1.3 +softwareVersion: 7.1.5 url: 'https://github.com/KnowageLabs/Knowage-Server.git' usedBy: - Azienda Unità Locale Sanitaria di Modena + - Enav S.p.A. + - Regione Emilia Romagna diff --git a/qbecore/pom.xml b/qbecore/pom.xml index efe332eb6a2..021a7ac0186 100644 --- a/qbecore/pom.xml +++ b/qbecore/pom.xml @@ -130,7 +130,7 @@ mysql mysql-connector-java - 5.1.38 + 8.0.16 test diff --git a/qbecore/src/main/java/it/eng/qbe/dataset/QbeDataSet.java b/qbecore/src/main/java/it/eng/qbe/dataset/QbeDataSet.java index 411dee40f69..bf05b8dde6e 100644 --- a/qbecore/src/main/java/it/eng/qbe/dataset/QbeDataSet.java +++ b/qbecore/src/main/java/it/eng/qbe/dataset/QbeDataSet.java @@ -38,6 +38,7 @@ import it.eng.qbe.datasource.dataset.DataSetDataSource; import it.eng.qbe.datasource.dataset.DataSetDriver; import it.eng.qbe.datasource.jpa.JPADataSource; +import it.eng.qbe.model.accessmodality.IModelAccessModality; import it.eng.qbe.query.Query; import it.eng.qbe.query.TimeAggregationHandler; import it.eng.qbe.query.catalogue.QueryCatalogue; @@ -135,7 +136,8 @@ private void init() { QueryCatalogue catalogue = getCatalogue(jsonQuery, qbeDataSource); Query query = catalogue.getFirstQuery(); setQuery(query); - initDs(qbeDataSource, query); + Query filteredQuery = filterQueryWithProfileAttributes(qbeDataSource, query); + initDs(qbeDataSource, filteredQuery); } } @@ -158,6 +160,12 @@ public void initDs(it.eng.qbe.datasource.IDataSource qbeDataSource, Query query) ds.setDrivers(this.getDrivers()); } + public Query filterQueryWithProfileAttributes(it.eng.qbe.datasource.IDataSource qbeDataSource, Query query) { + IModelAccessModality accessModality = qbeDataSource.getModelAccessModality(); + Query filteredQuery = accessModality.getFilteredStatement(query, qbeDataSource, attributes); + return filteredQuery; + } + @Override public void loadData(int offset, int fetchSize, int maxResults) { init(); diff --git a/qbecore/src/main/java/it/eng/qbe/datasource/jpa/JPAPersistenceManager.java b/qbecore/src/main/java/it/eng/qbe/datasource/jpa/JPAPersistenceManager.java index 8a20d292746..1e5e4c654a5 100644 --- a/qbecore/src/main/java/it/eng/qbe/datasource/jpa/JPAPersistenceManager.java +++ b/qbecore/src/main/java/it/eng/qbe/datasource/jpa/JPAPersistenceManager.java @@ -45,7 +45,11 @@ import org.json.JSONException; import org.json.JSONObject; +import it.eng.qbe.datasource.IDataSource; import it.eng.qbe.datasource.IPersistenceManager; +import it.eng.qbe.model.structure.IModelEntity; +import it.eng.qbe.model.structure.IModelField; +import it.eng.qbe.model.structure.IModelStructure; import it.eng.spagobi.engines.qbe.registry.bo.RegistryConfiguration; import it.eng.spagobi.engines.qbe.registry.bo.RegistryConfiguration.Column; import it.eng.spagobi.utilities.assertion.Assert; @@ -208,7 +212,7 @@ public Integer insertRecord(JSONObject aRecord, RegistryConfiguration registryCo logger.debug("Column [" + attributeName + "] is a foreign key"); if (aRecord.get(attributeName) != null && !aRecord.get(attributeName).equals("")) { logger.debug("search foreign reference for value " + aRecord.get(attributeName)); - manageForeignKey(targetEntity, column, newObj, attributeName, aRecord, columnDepends, entityManager); + manageForeignKey(targetEntity, column, newObj, attributeName, aRecord, columnDepends, entityManager, registryConf.getColumns()); } else { // no value in column, insert null logger.debug("No value for " + attributeName + ": keep it null"); @@ -330,7 +334,7 @@ public void updateRecord(JSONObject aRecord, RegistryConfiguration registryConf) if (!column.isInfoColumn()) { if (column.getSubEntity() != null) { logger.debug("Column [" + attributeName + "] is a foreign key"); - manageForeignKey(targetEntity, column, obj, attributeName, aRecord, columnDepends, entityManager); + manageForeignKey(targetEntity, column, obj, attributeName, aRecord, columnDepends, entityManager, registryConf.getColumns()); } else { logger.debug("Column [" + attributeName + "] is a normal column"); manageProperty(targetEntity, obj, attributeName, aRecord); @@ -471,9 +475,18 @@ public String getKeyAttributeName(EntityType entity) { return keyName; } + private void addRecursiveDependenciesTo(LinkedHashMap filtersForRef, List columns, Column c, JSONObject aRecord) throws JSONException { + for (Column column : columns) { + if (!column.getField().equals(c.getField()) && column.getDependences() != null && column.getDependences().equals(c.getField())) { + addRecursiveDependenciesTo(filtersForRef, columns, column, aRecord); + filtersForRef.put(column.getField(), aRecord.get(column.getField())); + } + } + } + // case of foreign key private void manageForeignKey(EntityType targetEntity, Column c, Object obj, String aKey, JSONObject aRecord, List lstDependences, - EntityManager entityManager) { + EntityManager entityManager, List columns) { logger.debug("column " + aKey + " is a FK"); @@ -489,16 +502,17 @@ private void manageForeignKey(EntityType targetEntity, Column c, Object obj, Str try { LinkedHashMap filtersForRef = new LinkedHashMap(); filtersForRef.put(c.getField(), (aRecord.get(aKey))); - // add dependences if they are - if (lstDependences != null) { + + addRecursiveDependenciesTo(filtersForRef, columns, c, aRecord); + + // add dependences FROM if they are + if (lstDependences == null || lstDependences != null) { for (int i = 0; i < lstDependences.size(); i++) { Column tmpDep = (Column) lstDependences.get(i); - if (!tmpDep.isInfoColumn() && tmpDep.getSubEntity() != null) - filtersForRef.put(tmpDep.getSubEntity() + "." + tmpDep.getField(), (aRecord.get(tmpDep.getField()))); - else if (!tmpDep.isInfoColumn() && tmpDep.getSubEntity() == null) - filtersForRef.put(tmpDep.getField(), (aRecord.get(tmpDep.getField()))); + addRecursiveDependenciesFrom(targetEntity, aRecord, entityType, filtersForRef, tmpDep, c, columns); } } + Object referenced = getReferencedObjectJPA(entityManager, entityNameNoPkgSub, filtersForRef); Class clas = targetEntity.getJavaType(); @@ -517,6 +531,54 @@ else if (!tmpDep.isInfoColumn() && tmpDep.getSubEntity() == null) } } + private void addRecursiveDependenciesFrom(EntityType targetEntity, JSONObject aRecord, String entityType, LinkedHashMap filtersForRef, Column tmpDep, + Column c, List columns) throws JSONException { + if (!tmpDep.isInfoColumn() && tmpDep.getSubEntity() != null) { + IDataSource model = getDataSource(); + IModelStructure structure = model.getModelStructure(); + String targetEntityName = targetEntity.getJavaType().getName(); + IModelField selectField = structure + .getField(targetEntityName + "::" + tmpDep.getSubEntity() + "(" + tmpDep.getForeignKey() + "):" + tmpDep.getField()); + IModelEntity parentEntity = selectField.getParent(); + logger.debug("Parent entity is " + parentEntity.getUniqueName()); + IModelEntity rootEntity = structure.getRootEntity(parentEntity); + logger.debug("Relevant root entity is " + rootEntity.getUniqueName()); + List fields = rootEntity.getAllFields(); + Iterator it = fields.iterator(); + String dependencyEntityId = null; + EntityType dependencyEntityType = null; + while (it.hasNext()) { + IModelField aField = (IModelField) it.next(); + if (aField.getName().equals(selectField.getName())) { + dependencyEntityId = aField.getUniqueName(); + break; + } + } + + if (dependencyEntityId.startsWith(entityType)) { + dependencyEntityId = dependencyEntityId.substring(dependencyEntityId.indexOf(entityType) + entityType.length() + 1); + } else { + dependencyEntityId = tmpDep.getSubEntity() + "." + dependencyEntityId; + } + + addRecursiveDependenciesTo(filtersForRef, columns, getColumn(columns, dependencyEntityId), aRecord); + + filtersForRef.put(dependencyEntityId, aRecord.get(tmpDep.getField())); + + } else if (!tmpDep.isInfoColumn() && tmpDep.getSubEntity() == null) { + filtersForRef.put(tmpDep.getField(), (aRecord.get(tmpDep.getField()))); + } + } + + private Column getColumn(List columns, String columnName) { + for (Column column : columns) { + if (column.getField().equals(columnName)) { + return column; + } + } + return null; + } + private void manageProperty(EntityType targetEntity, Object obj, String aKey, JSONObject aRecord) { logger.debug("IN"); @@ -578,28 +640,28 @@ private Object convertValue(Object valueObj, Attribute attribute) { } // BigInteger, Integer, Long, Short, Byte if (Integer.class.getName().equals(clazzName)) { - logger.error(">>> Integer"); + logger.debug(">>> Integer"); toReturn = Integer.parseInt(value); } else if (Double.class.getName().equals(clazzName)) { - logger.error(">>> Double"); + logger.debug(">>> Double"); toReturn = new Double(value); } else if (BigDecimal.class.getName().equals(clazzName)) { - logger.error(">>> BigDecimal"); + logger.debug(">>> BigDecimal"); toReturn = new BigDecimal(value); } else if (BigInteger.class.getName().equals(clazzName)) { - logger.error(">>> BigInteger"); + logger.debug(">>> BigInteger"); toReturn = new BigInteger(value); } else if (Long.class.getName().equals(clazzName)) { - logger.error(">>> Long"); + logger.debug(">>> Long"); toReturn = new Long(value); } else if (Short.class.getName().equals(clazzName)) { - logger.error(">>> Short"); + logger.debug(">>> Short"); toReturn = new Short(value); } else if (Byte.class.getName().equals(clazzName)) { - logger.error(">>> Byte"); + logger.debug(">>> Byte"); toReturn = new Byte(value); } else { - logger.error(">>> Float"); + logger.debug(">>> Float"); toReturn = new Float(value); } } else if (String.class.isAssignableFrom(clazz)) { @@ -613,6 +675,9 @@ private Object convertValue(Object valueObj, Attribute attribute) { SimpleDateFormat sdfISO = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); // SimpleDateFormat sdf = new // SimpleDateFormat("MM/dd/yyyy hh:mm:ss"); + if (value.equals("") || value.toLowerCase().equals("null")) { + return null; + } if (!value.equals("") && !value.contains(":")) { value += " 00:00:00"; } @@ -629,11 +694,15 @@ private Object convertValue(Object valueObj, Attribute attribute) { } } else if (Date.class.isAssignableFrom(clazz)) { - // TODO manage dates - SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy"); + + if (value.equals("") || value.toLowerCase().equals("null")) { + return null; + } + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); try { - toReturn = sdf.parse(value); + toReturn = new java.sql.Date(sdf.parse(value).getTime()); } catch (ParseException e) { logger.error("Unparsable date", e); } diff --git a/qbecore/src/main/java/it/eng/qbe/model/structure/IModelField.java b/qbecore/src/main/java/it/eng/qbe/model/structure/IModelField.java index 9807363769f..b127a6b4ed2 100644 --- a/qbecore/src/main/java/it/eng/qbe/model/structure/IModelField.java +++ b/qbecore/src/main/java/it/eng/qbe/model/structure/IModelField.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,25 +11,40 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package it.eng.qbe.model.structure; + import it.eng.spagobi.utilities.objects.Couple; public interface IModelField extends IModelNode { - public String getUniqueName(); - public Couple getQueryName(); - public String getType(); - public void setType(String type); - public int getLength(); - public void setLength(int length); - public int getPrecision() ; - public void setPrecision(int precision); - public boolean isKey() ; - public void setKey(boolean key); - public IModelField clone(IModelEntity newParent); + public String getUniqueName(); + + public Couple getQueryName(); + + public String getType(); + + public void setType(String type); + + public int getLength(); + + public void setLength(int length); + + public int getPrecision(); + + public void setPrecision(int precision); + + public boolean isKey(); + + public void setKey(boolean key); + + public IModelField clone(IModelEntity newParent); + + public Class getJavaClass(); + + public void setJavaClass(Class javaClass); } diff --git a/qbecore/src/main/java/it/eng/qbe/model/structure/ModelField.java b/qbecore/src/main/java/it/eng/qbe/model/structure/ModelField.java index 99ea2249ac4..d77bceac6e7 100644 --- a/qbecore/src/main/java/it/eng/qbe/model/structure/ModelField.java +++ b/qbecore/src/main/java/it/eng/qbe/model/structure/ModelField.java @@ -1,7 +1,7 @@ /* * Knowage, Open Source Business Intelligence suite * Copyright (C) 2016 Engineering Ingegneria Informatica S.p.A. - * + * * Knowage is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. - * + * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ @@ -24,153 +24,173 @@ import it.eng.spagobi.utilities.objects.Couple; - /** * @author Andrea Gioia */ public class ModelField extends AbstractModelNode implements IModelField { - + private boolean key; private String type; private int length; private int precision; - - //private String datamartName; - + private Class javaClass; + + // private String datamartName; + protected ModelField() { // in order to let subclass in this package to relax constraints imposed by the public constructor // DataMartField(String name, DataMartEntity parent). Ex. DataMartCalculatedField // can be created by themself without a pre-existing parent entity. initProperties(); } - + public ModelField(String name, IModelEntity parent) { setStructure(parent.getStructure()); - setId( getStructure().getNextId() ); + setId(getStructure().getNextId()); setName(name); setParent(parent); - initProperties(); + initProperties(); } + @Override public String getUniqueName() { - + String parentViewName = getParent().getPropertyAsString("parentView"); - if(parentViewName!= null) { - return parentViewName+":"+getParent().getType() + ":" + getName(); + if (parentViewName != null) { + return parentViewName + ":" + getParent().getType() + ":" + getName(); } - if(getParent().getParent() == null) { + if (getParent().getParent() == null) { return getParent().getType() + ":" + getName(); } return getParent().getUniqueName() + ":" + getName(); } - - + + @Override public Couple getQueryName() { String fieldName = ""; - + IModelEntity entity = getParent(); - if(entity.getParent() != null) { - if(entity.getParent() instanceof ModelViewEntity){ + if (entity.getParent() != null) { + if (entity.getParent() instanceof ModelViewEntity) { fieldName = getName(); - return new Couple (fieldName, entity); + return new Couple(fieldName, entity); } - fieldName = toLowerCase( entity.getName() ); + fieldName = toLowerCase(entity.getName()); entity = entity.getParent(); } - while(entity.getParent() != null) { - if(entity.getParent() instanceof ModelViewEntity){ - if(!fieldName.equalsIgnoreCase("")) fieldName += "."; - fieldName = fieldName+getName(); - return new Couple (fieldName, entity); + while (entity.getParent() != null) { + if (entity.getParent() instanceof ModelViewEntity) { + if (!fieldName.equalsIgnoreCase("")) + fieldName += "."; + fieldName = fieldName + getName(); + return new Couple(fieldName, entity); } - fieldName = toLowerCase( entity.getName() ) + "." + fieldName; + fieldName = toLowerCase(entity.getName()) + "." + fieldName; entity = entity.getParent(); - } - if(!fieldName.equalsIgnoreCase("")) fieldName += "."; + } + if (!fieldName.equalsIgnoreCase("")) + fieldName += "."; fieldName += getName(); - - return new Couple (fieldName, null); + + return new Couple(fieldName, null); } - - + private String toLowerCase(String str) { /* - String head = str.substring(0,1); - String tail = str.substring(1, str.length()); - - return head.toLowerCase() + tail; - */ + * String head = str.substring(0,1); String tail = str.substring(1, str.length()); + * + * return head.toLowerCase() + tail; + */ return str; } - + + @Override public String getType() { return type; } - + + @Override public void setType(String type) { this.type = type; } - + + @Override public int getLength() { return length; } - + + @Override public void setLength(int length) { this.length = length; } + @Override public int getPrecision() { return precision; } + @Override public void setPrecision(int precision) { this.precision = precision; } + @Override public boolean isKey() { return key; } + @Override public void setKey(boolean key) { this.key = key; } - + + @Override public String toString() { - return getName() + "(id="+getId() - +"; parent:" + (getParent()==null?"NULL": getParent().getName()) - +"; type="+type - +"; length="+length - +"; precision="+precision - +")"; + return getName() + "(id=" + getId() + "; parent:" + (getParent() == null ? "NULL" : getParent().getName()) + "; type=" + type + "; length=" + length + + "; precision=" + precision + ")"; } - - public IModelField clone(IModelEntity newParent){ + @Override + public IModelField clone(IModelEntity newParent) { IModelField field = new ModelField(name, newParent); field.setKey(this.key); field.setType(this.type); field.setLength(this.length); field.setPrecision(this.precision); - Map properties2 = new HashMap(); + Map properties2 = new HashMap(); for (Iterator iterator = properties.keySet().iterator(); iterator.hasNext();) { - String key= (String)iterator.next(); - String o = (String)properties.get(key); - if(o==null){ + String key = (String) iterator.next(); + String o = (String) properties.get(key); + if (o == null) { properties2.put(key.substring(0), null); - }else{ + } else { properties2.put(key.substring(0), o.substring(0)); } - + } field.setProperties(properties2); return field; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see it.eng.qbe.model.structure.IModelNode#getParentViews() */ + @Override public List getParentViews() { return super.getParentViews(this.getParent()); } - + + @Override + public Class getJavaClass() { + return javaClass; + } + + @Override + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + + } + } diff --git a/qbecore/src/main/java/it/eng/qbe/model/structure/builder/jpa/JPAModelStructureBuilder.java b/qbecore/src/main/java/it/eng/qbe/model/structure/builder/jpa/JPAModelStructureBuilder.java index fd3831752ff..92b1c1f7a34 100644 --- a/qbecore/src/main/java/it/eng/qbe/model/structure/builder/jpa/JPAModelStructureBuilder.java +++ b/qbecore/src/main/java/it/eng/qbe/model/structure/builder/jpa/JPAModelStructureBuilder.java @@ -69,8 +69,7 @@ public class JPAModelStructureBuilder extends AbstractModelStructureBuilder { /** * Constructor * - * @param dataSource - * the JPA DataSource + * @param dataSource the JPA DataSource */ public JPAModelStructureBuilder(JPADataSource dataSource) { if (dataSource == null) { @@ -330,8 +329,7 @@ private String getEntityNameFromEntityType(String entityType) { /** * This method adds the normal fields to the model entry structure * - * @param modelEntity: - * the model entity to complete adding normal fields + * @param modelEntity: the model entity to complete adding normal fields * * @return a list of entities in ONE_TO_MANY relationship with the entity passed in as parameter (i.e. entities whose input entity is related to by means of * e foreign key - MANY_TO_ONE relatioship) @@ -402,10 +400,8 @@ public List addNormalFields(IModelEntity modelEntity) { /** * Add an attribute to the model * - * @param attr - * the attribute - * @param dataMartEntity - * the parent entity + * @param attr the attribute + * @param dataMartEntity the parent entity */ private void addField(Attribute attr, IModelEntity dataMartEntity, String keyPrefix) { String n = attr.getName(); @@ -421,6 +417,7 @@ private void addField(Attribute attr, IModelEntity dataMartEntity, String keyPre modelField.setType(type); modelField.setPrecision(precision); modelField.setLength(scale); + modelField.setJavaClass(c); propertiesInitializer.addProperties(modelField); } @@ -509,8 +506,7 @@ public JPADataSource getDataSource() { } /** - * @param JPADataSource - * the datasource to set + * @param JPADataSource the datasource to set */ public void setDataSource(JPADataSource dataSource) { this.dataSource = dataSource; @@ -524,8 +520,7 @@ public EntityManager getEntityManager() { } /** - * @param entityManager - * the entityManager to set + * @param entityManager the entityManager to set */ public void setEntityManager(EntityManager entityManager) { this.entityManager = entityManager; diff --git a/qbecore/src/main/java/it/eng/qbe/query/Query.java b/qbecore/src/main/java/it/eng/qbe/query/Query.java index 60a7e3c452b..8a7c074532f 100644 --- a/qbecore/src/main/java/it/eng/qbe/query/Query.java +++ b/qbecore/src/main/java/it/eng/qbe/query/Query.java @@ -254,7 +254,7 @@ public boolean isEmpty() { @Override public void addSelectFiled(String fieldUniqueName, String function, String fieldAlias, boolean include, boolean visible, boolean groupByField, String orderType, String pattern) { - selectFields.add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, null, null)); + selectFields.add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, null, null, null)); } /** @@ -266,8 +266,14 @@ public void addSelectFiled(String fieldUniqueName, String function, String field @Override public void addSelectFiled(String fieldUniqueName, String function, String fieldAlias, boolean include, boolean visible, boolean groupByField, String orderType, String pattern, String orderColumn) { - selectFields - .add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, null, null, orderColumn)); + selectFields.add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, null, null, + orderColumn, null)); + } + + public void addSelectFiled(String fieldUniqueName, String function, String fieldAlias, boolean include, boolean visible, boolean groupByField, + String orderType, String pattern, String orderColumn, Class javaClass) { + selectFields.add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, null, null, + orderColumn, javaClass)); } /** @@ -276,10 +282,10 @@ public void addSelectFiled(String fieldUniqueName, String function, String field * * @modifiedBy Danilo Ristovski (danristo, danilo.ristovski@mht.net) */ - public void addSelectFiled(String fieldUniqueName, String function, String fieldAlias, boolean include, boolean visible, boolean groupByField, - String orderType, String pattern, String temporalOperand, String temporalOperandParameter) { + public void addSelectField(String fieldUniqueName, String function, String fieldAlias, boolean include, boolean visible, boolean groupByField, + String orderType, String pattern, String temporalOperand, String temporalOperandParameter, Class javaClass) { selectFields.add(new SimpleSelectField(fieldUniqueName, function, fieldAlias, include, visible, groupByField, orderType, pattern, temporalOperand, - temporalOperandParameter)); + temporalOperandParameter, javaClass)); } public void addSelectFiled(SimpleSelectField timeIdField) { @@ -367,9 +373,8 @@ public HavingField getHavingFieldByName(String fname) { } /** - * @param onlyIncluded - * true to return all the select fields. false to include only the select fields actually included in the select clause of the generated statemet - * (i.e it is possible for a select field to be used only in 'order by' or in 'group by' clause of the statement) + * @param onlyIncluded true to return all the select fields. false to include only the select fields actually included in the select clause of the generated + * statemet (i.e it is possible for a select field to be used only in 'order by' or in 'group by' clause of the statement) * * @return a List of all selected fields (ISelectField). All the field types are included (i.e. simple fields, calculated fields and inline calculated * fields). Never returns null. If there are no selected fields in the query it returns an empty list. @@ -472,9 +477,8 @@ public int getSelectFieldIndex(String uniqueName) { /** * Returns a list of of simple select fields (no inlineCalculatedSelectField & calculatedSelectField) * - * @param onlyIncluded - * if true the returned list will include only the simple select fields actually included in the select statement. All the simple select fields - * will be returned otherwise. + * @param onlyIncluded if true the returned list will include only the simple select fields actually included in the select statement. All the simple select + * fields will be returned otherwise. * * @return a list of SimpleSelectField. It never returns null. If there are not fields in select clause it will return an empty list. */ @@ -515,9 +519,8 @@ public List getCalculatedSelectFields(boolean onlyIncluded) { /** * Returns the list of inline calculated fields included in select clause (no simpleSelectField & calculatedSelectField) * - * @param onlyIncluded - * if true the returned list will include only the inline calculated fields actually included in the select statement. All the inline calculated - * fields will be returned otherwise. + * @param onlyIncluded if true the returned list will include only the inline calculated fields actually included in the select statement. All the inline + * calculated fields will be returned otherwise. * * @return a list of InLineCalculatedSelectField. It never returns null. If there are not inline calculated fields in select clause it will return an empty * list. diff --git a/qbecore/src/main/java/it/eng/qbe/query/SimpleSelectField.java b/qbecore/src/main/java/it/eng/qbe/query/SimpleSelectField.java index 65ceca760a7..18b5ac7d4ac 100644 --- a/qbecore/src/main/java/it/eng/qbe/query/SimpleSelectField.java +++ b/qbecore/src/main/java/it/eng/qbe/query/SimpleSelectField.java @@ -35,8 +35,10 @@ public class SimpleSelectField extends AbstractSelectField { private String temporalOperand; private String temporalOperandParameter; + private Class javaClass; + public SimpleSelectField(String uniqueName, String function, String alias, boolean include, boolean visible, boolean groupByField, String orderType, - String pattern, String temporalOperand, String temporalOperandParameter) { + String pattern, String temporalOperand, String temporalOperandParameter, Class javaClass) { super(alias, ISelectField.SIMPLE_FIELD, include, visible); @@ -47,10 +49,11 @@ public SimpleSelectField(String uniqueName, String function, String alias, boole setPattern(pattern); setTemporalOperand(temporalOperand); setTemporalOperandParameter(temporalOperandParameter); + setJavaClass(javaClass); } public SimpleSelectField(String uniqueName, String function, String alias, boolean include, boolean visible, boolean groupByField, String orderType, - String pattern, String temporalOperand, String temporalOperandParameter, String orderColumn) { + String pattern, String temporalOperand, String temporalOperandParameter, String orderColumn, Class javaClass) { super(alias, ISelectField.SIMPLE_FIELD, include, visible); @@ -70,12 +73,14 @@ public SimpleSelectField(String uniqueName, String function, String alias, boole setPattern(pattern); setTemporalOperand(temporalOperand); setTemporalOperandParameter(temporalOperandParameter); + setJavaClass(javaClass); } public SimpleSelectField(SimpleSelectField field) { - this(field.getUniqueName(), field.getFunction().getName(), field.getAlias(), field.isIncluded(), field.isVisible(), field.isGroupByField(), field - .getOrderType(), field.getPattern(), field.getTemporalOperand(), field.getTemporalOperandParameter(), field.getOrderColumn()); + this(field.getUniqueName(), field.getFunction().getName(), field.getAlias(), field.isIncluded(), field.isVisible(), field.isGroupByField(), + field.getOrderType(), field.getPattern(), field.getTemporalOperand(), field.getTemporalOperandParameter(), field.getOrderColumn(), + field.getJavaClass()); } public IAggregationFunction getFunction() { @@ -175,4 +180,12 @@ private String getIdForEquals() { return this.getAlias() + '|' + this.getName(); } + public Class getJavaClass() { + return javaClass; + } + + public void setJavaClass(Class javaClass) { + this.javaClass = javaClass; + } + } diff --git a/qbecore/src/main/java/it/eng/qbe/query/TimeAggregationHandler.java b/qbecore/src/main/java/it/eng/qbe/query/TimeAggregationHandler.java index 243ed70d34a..21129856610 100644 --- a/qbecore/src/main/java/it/eng/qbe/query/TimeAggregationHandler.java +++ b/qbecore/src/main/java/it/eng/qbe/query/TimeAggregationHandler.java @@ -739,8 +739,8 @@ private void addTimeIdToQuery(Query query, IModelEntity temporalDimension, Strin String pattern = null; String temporalOperand = null; String temporalOperandParameter = null; - query.addSelectFiled(fieldUniqueName, function, temporalDimensionId, include, visible, groupByField, orderType, - pattern, temporalOperand, temporalOperandParameter); + query.addSelectField(fieldUniqueName, function, temporalDimensionId, include, visible, groupByField, orderType, + pattern, temporalOperand, temporalOperandParameter, null); } private void addYearToQuery(Query query, IModelEntity temporalDimension, @@ -754,8 +754,8 @@ private void addYearToQuery(Query query, IModelEntity temporalDimension, String pattern = null; String temporalOperand = null; String temporalOperandParameter = null; - query.addSelectFiled(fieldUniqueName, function, "YEAR", include, visible, groupByField, orderType, pattern, - temporalOperand, temporalOperandParameter); + query.addSelectField(fieldUniqueName, function, "YEAR", include, visible, groupByField, orderType, pattern, + temporalOperand, temporalOperandParameter, null); } private void addSumFunctionToAllMeasureInSelect(List selectFields) { @@ -805,8 +805,8 @@ private Set addMissingGroupByToTheQuery(Query query, List String pattern = null; String temporalOperand = null; String temporalOperandParameter = null; - query.addSelectFiled(fieldUniqueName, null, inlineFilterType, include, visible, groupByField, orderType, - pattern, temporalOperand, temporalOperandParameter); + query.addSelectField(fieldUniqueName, null, inlineFilterType, include, visible, groupByField, orderType, + pattern, temporalOperand, temporalOperandParameter, null); aliasesToBeRemovedAfterExecution.add(fieldUniqueName); } diff --git a/qbecore/src/main/java/it/eng/qbe/query/serializer/json/QueryJSONDeserializer.java b/qbecore/src/main/java/it/eng/qbe/query/serializer/json/QueryJSONDeserializer.java index f258133f9da..441a10a03f4 100644 --- a/qbecore/src/main/java/it/eng/qbe/query/serializer/json/QueryJSONDeserializer.java +++ b/qbecore/src/main/java/it/eng/qbe/query/serializer/json/QueryJSONDeserializer.java @@ -213,8 +213,8 @@ private void deserializeFields(JSONArray fieldsJSON, IDataSource dataSource, Que } // if (StringUtilities.isEmpty(temporalOperand)) { - query.addSelectFiled(field.getUniqueName(), funct, alias, included, visible, group.equalsIgnoreCase("true"), order, pattern, - temporalOperand, temporalOperandParameter); + query.addSelectField(field.getUniqueName(), funct, alias, included, visible, group.equalsIgnoreCase("true"), order, pattern, + temporalOperand, temporalOperandParameter, field.getJavaClass() != null ? field.getJavaClass() : null); // } // Handle temporal operands // else { diff --git a/qbecore/src/main/java/it/eng/qbe/statement/AbstractQbeDataSet.java b/qbecore/src/main/java/it/eng/qbe/statement/AbstractQbeDataSet.java index c8e3b90d8a2..777e0d7e5f1 100644 --- a/qbecore/src/main/java/it/eng/qbe/statement/AbstractQbeDataSet.java +++ b/qbecore/src/main/java/it/eng/qbe/statement/AbstractQbeDataSet.java @@ -93,25 +93,30 @@ public IDataStore getDataStore() { protected IMetaData getDataStoreMeta(Query query) { IMetaData dataStoreMeta; - ISelectField queryFiled; + ISelectField queryField; FieldMetadata dataStoreFieldMeta; Map aliasSelectedFields = QueryJSONSerializer.getFieldsNature(query, statement.getDataSource()); - dataStoreMeta = new MetaData(); Iterator fieldsIterator = query.getSelectFields(true).iterator(); while (fieldsIterator.hasNext()) { - queryFiled = (ISelectField) fieldsIterator.next(); + queryField = (ISelectField) fieldsIterator.next(); dataStoreFieldMeta = new FieldMetadata(); - dataStoreFieldMeta.setAlias(queryFiled.getAlias()); - if (queryFiled.isSimpleField()) { - SimpleSelectField dataMartSelectField = (SimpleSelectField) queryFiled; - dataStoreFieldMeta.setName(((SimpleSelectField) queryFiled).getAlias()); + dataStoreFieldMeta.setAlias(queryField.getAlias()); + if (queryField.isSimpleField()) { + SimpleSelectField dataMartSelectField = (SimpleSelectField) queryField; + dataStoreFieldMeta.setName(((SimpleSelectField) queryField).getAlias()); dataStoreFieldMeta.setProperty("calculated", new Boolean(false)); dataStoreFieldMeta.setProperty("uniqueName", dataMartSelectField.getUniqueName()); - dataStoreFieldMeta.setType(Object.class); + + if (dataMartSelectField.getFunction().getName().equals("NONE") && dataMartSelectField.getJavaClass() != null) { + dataStoreFieldMeta.setType(dataMartSelectField.getJavaClass()); + } else { + dataStoreFieldMeta.setType(Object.class); + } + String format = dataMartSelectField.getPattern(); if (format != null && !format.trim().equals("")) { dataStoreFieldMeta.setProperty("format", format); @@ -136,34 +141,34 @@ protected IMetaData getDataStoreMeta(Query query) { dataStoreFieldMeta.setFieldType(FieldType.ATTRIBUTE); } - } else if (queryFiled.isCalculatedField()) { - CalculatedSelectField claculatedQueryField = (CalculatedSelectField) queryFiled; - dataStoreFieldMeta.setName(claculatedQueryField.getAlias()); + } else if (queryField.isCalculatedField()) { + CalculatedSelectField calculatedQueryField = (CalculatedSelectField) queryField; + dataStoreFieldMeta.setName(calculatedQueryField.getAlias()); dataStoreFieldMeta.setProperty("calculated", new Boolean(true)); dataStoreFieldMeta.setProperty("calculatedExpert", new Boolean(true)); // FIXME also calculated field must have uniquename for // uniformity - dataStoreFieldMeta.setProperty("uniqueName", claculatedQueryField.getAlias()); - DataSetVariable variable = new DataSetVariable(claculatedQueryField.getAlias(), claculatedQueryField.getType(), - claculatedQueryField.getExpression()); + dataStoreFieldMeta.setProperty("uniqueName", calculatedQueryField.getAlias()); + DataSetVariable variable = new DataSetVariable(calculatedQueryField.getAlias(), calculatedQueryField.getType(), + calculatedQueryField.getExpression()); dataStoreFieldMeta.setProperty("variable", variable); dataStoreFieldMeta.setType(variable.getTypeClass()); - } else if (queryFiled.isInLineCalculatedField()) { - InLineCalculatedSelectField claculatedQueryField = (InLineCalculatedSelectField) queryFiled; - dataStoreFieldMeta.setName(claculatedQueryField.getAlias()); + } else if (queryField.isInLineCalculatedField()) { + InLineCalculatedSelectField calculatedQueryField = (InLineCalculatedSelectField) queryField; + dataStoreFieldMeta.setName(calculatedQueryField.getAlias()); dataStoreFieldMeta.setProperty("calculated", new Boolean(false)); // FIXME also calculated field must have uniquename for // uniformity - dataStoreFieldMeta.setProperty("uniqueName", claculatedQueryField.getAlias()); - DataSetVariable variable = new DataSetVariable(claculatedQueryField.getAlias(), claculatedQueryField.getType(), - claculatedQueryField.getExpression()); + dataStoreFieldMeta.setProperty("uniqueName", calculatedQueryField.getAlias()); + DataSetVariable variable = new DataSetVariable(calculatedQueryField.getAlias(), calculatedQueryField.getType(), + calculatedQueryField.getExpression()); dataStoreFieldMeta.setProperty("variable", variable); dataStoreFieldMeta.setType(variable.getTypeClass()); - String nature = queryFiled.getNature(); + String nature = queryField.getNature(); if (nature == null) { - nature = QueryJSONSerializer.getInLinecalculatedFieldNature(claculatedQueryField.getExpression(), aliasSelectedFields); + nature = QueryJSONSerializer.getInLinecalculatedFieldNature(calculatedQueryField.getExpression(), aliasSelectedFields); } dataStoreFieldMeta.setProperty("nature", nature); if (nature.equalsIgnoreCase(QuerySerializationConstants.FIELD_NATURE_MANDATORY_MEASURE) @@ -173,7 +178,7 @@ protected IMetaData getDataStoreMeta(Query query) { dataStoreFieldMeta.setFieldType(FieldType.ATTRIBUTE); } } - dataStoreFieldMeta.setProperty("visible", new Boolean(queryFiled.isVisible())); + dataStoreFieldMeta.setProperty("visible", new Boolean(queryField.isVisible())); dataStoreMeta.addFiedMeta(dataStoreFieldMeta); } diff --git a/screenshots/knowage-cockpit.jpg b/screenshots/knowage-cockpit.jpg new file mode 100644 index 00000000000..185b3f7853a Binary files /dev/null and b/screenshots/knowage-cockpit.jpg differ diff --git a/screenshots/knowage-cockpit2.jpg b/screenshots/knowage-cockpit2.jpg new file mode 100644 index 00000000000..54dd08cf1f2 Binary files /dev/null and b/screenshots/knowage-cockpit2.jpg differ diff --git a/screenshots/knowage-covid-italy-regional.png b/screenshots/knowage-covid-italy-regional.png new file mode 100644 index 00000000000..6d499eee119 Binary files /dev/null and b/screenshots/knowage-covid-italy-regional.png differ diff --git a/screenshots/knowage-kpi.jpg b/screenshots/knowage-kpi.jpg new file mode 100644 index 00000000000..6fb50558328 Binary files /dev/null and b/screenshots/knowage-kpi.jpg differ diff --git a/screenshots/knowage-map.jpg b/screenshots/knowage-map.jpg new file mode 100644 index 00000000000..a057dc091a4 Binary files /dev/null and b/screenshots/knowage-map.jpg differ diff --git a/screenshots/knowage-responsive2.jpg b/screenshots/knowage-responsive2.jpg new file mode 100644 index 00000000000..adf4d266de6 Binary files /dev/null and b/screenshots/knowage-responsive2.jpg differ