blob: f909c33b6ff107380e57a4d71ea82878d3ea307e [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.infrastructure.dataqueries.domain;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils;
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
import com.google.gson.JsonArray;
@Entity
@Table(name = "stretchy_report", uniqueConstraints = { @UniqueConstraint(columnNames = { "report_name" }, name = "unq_report_name") })
public final class Report extends AbstractPersistableCustom<Long> {
@Column(name = "report_name", nullable = false, unique = true)
private String reportName;
@Column(name = "report_type", nullable = false)
private String reportType;
@Column(name = "report_subtype")
private String reportSubType;
@Column(name = "report_category")
private String reportCategory;
@Column(name = "description")
private String description;
@Column(name = "core_report", nullable = false)
private boolean coreReport;
// only defines if report should appear in reference app UI List
@Column(name = "use_report", nullable = false)
private boolean useReport;
@Column(name = "report_sql")
private String reportSql;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "report", orphanRemoval = true, fetch=FetchType.EAGER)
private Set<ReportParameterUsage> reportParameterUsages = new HashSet<>();
public static Report fromJson(final JsonCommand command, final Collection<String> reportTypes) {
String reportName = null;
String reportType = null;
String reportSubType = null;
String reportCategory = null;
String description = null;
boolean useReport = false;
String reportSql = null;
if (command.parameterExists("reportName")) {
reportName = command.stringValueOfParameterNamed("reportName");
}
if (command.parameterExists("reportType")) {
reportType = command.stringValueOfParameterNamed("reportType");
}
if (command.parameterExists("reportSubType")) {
reportSubType = command.stringValueOfParameterNamed("reportSubType");
}
if (command.parameterExists("reportCategory")) {
reportCategory = command.stringValueOfParameterNamed("reportCategory");
}
if (command.parameterExists("description")) {
description = command.stringValueOfParameterNamed("description");
}
if (command.parameterExists("useReport")) {
useReport = command.booleanPrimitiveValueOfParameterNamed("useReport");
}
if (command.parameterExists("reportSql")) {
reportSql = command.stringValueOfParameterNamed("reportSql");
}
return new Report(reportName, reportType, reportSubType, reportCategory, description, useReport, reportSql, reportTypes);
}
protected Report() {
//
}
public Report(final String reportName, final String reportType, final String reportSubType, final String reportCategory,
final String description, final boolean useReport, final String reportSql, final Collection<String> reportTypes) {
this.reportName = reportName;
this.reportType = reportType;
this.reportSubType = reportSubType;
this.reportCategory = reportCategory;
this.description = description;
this.coreReport = false;
this.useReport = useReport;
this.reportSql = reportSql;
validate(reportTypes);
}
public Map<String, Object> update(final JsonCommand command, final Collection<String> reportTypes) {
final Map<String, Object> actualChanges = new LinkedHashMap<>(8);
String paramName = "reportName";
if (command.isChangeInStringParameterNamed(paramName, this.reportName)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.reportName = StringUtils.defaultIfEmpty(newValue, null);
}
paramName = "reportType";
if (command.isChangeInStringParameterNamed(paramName, this.reportType)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.reportType = StringUtils.defaultIfEmpty(newValue, null);
}
paramName = "reportSubType";
if (command.isChangeInStringParameterNamed(paramName, this.reportSubType)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.reportSubType = StringUtils.defaultIfEmpty(newValue, null);
}
paramName = "reportCategory";
if (command.isChangeInStringParameterNamed(paramName, this.reportCategory)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.reportCategory = StringUtils.defaultIfEmpty(newValue, null);
}
paramName = "description";
if (command.isChangeInStringParameterNamed(paramName, this.description)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.description = StringUtils.defaultIfEmpty(newValue, null);
}
paramName = "useReport";
if (command.isChangeInBooleanParameterNamed(paramName, this.useReport)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.useReport = newValue;
}
paramName = "reportSql";
if (command.isChangeInStringParameterNamed(paramName, this.reportSql)) {
final String newValue = command.stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue);
this.reportSql = StringUtils.defaultIfEmpty(newValue, null);
}
final String reportParametersParamName = "reportParameters";
if (command.hasParameter(reportParametersParamName)) {
final JsonArray jsonArray = command.arrayOfParameterNamed(reportParametersParamName);
if (jsonArray != null) {
actualChanges.put(reportParametersParamName, command.jsonFragment(reportParametersParamName));
}
}
validate(reportTypes);
if (!actualChanges.isEmpty()) {
if (isCoreReport()) {
for (final String key : actualChanges.keySet()) {
if (!(key.equals("useReport"))) { throw new PlatformDataIntegrityException(
"error.msg.only.use.report.can.be.updated.for.core.report",
"Only the Use Report field can be updated for Core Reports", key); }
}
}
}
return actualChanges;
}
public boolean isCoreReport() {
return this.coreReport;
}
public ReportParameterUsage findReportParameterById(final Long reportParameterId) {
ReportParameterUsage reportParameterUsage = null;
for (final ReportParameterUsage rpu : this.reportParameterUsages) {
if (rpu.hasIdOf(reportParameterId)) {
reportParameterUsage = rpu;
break;
}
}
return reportParameterUsage;
}
private void validate(final Collection<String> reportTypes) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("report");
baseDataValidator.reset().parameter("reportName").value(this.reportName).notBlank().notExceedingLengthOf(100);
baseDataValidator.reset().parameter("reportType").value(this.reportType).notBlank().isOneOfTheseValues(reportTypes.toArray());
baseDataValidator.reset().parameter("reportSubType").value(this.reportSubType).notExceedingLengthOf(20);
if (StringUtils.isNotBlank(this.reportType)) {
if (this.reportType.equals("Chart")) {
baseDataValidator.reset().parameter("reportSubType").value(this.reportSubType)
.cantBeBlankWhenParameterProvidedIs("reportType", this.reportType)
.isOneOfTheseValues(new Object[] { "Bar", "Pie" });
} else {
baseDataValidator.reset().parameter("reportSubType").value(this.reportSubType)
.mustBeBlankWhenParameterProvidedIs("reportType", this.reportType);
}
}
baseDataValidator.reset().parameter("reportCategory").value(this.reportCategory).notExceedingLengthOf(45);
if (StringUtils.isNotBlank(this.reportType)) {
if ((this.reportType.equals("Table")) || (this.reportType.equals("Chart"))) {
baseDataValidator.reset().parameter("reportSql").value(this.reportSql)
.cantBeBlankWhenParameterProvidedIs("reportType", this.reportType);
} else {
baseDataValidator.reset().parameter("reportSql").value(this.reportSql)
.mustBeBlankWhenParameterProvidedIs("reportType", this.reportType);
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
}
public String getReportName() {
return this.reportName;
}
public boolean update(final Set<ReportParameterUsage> newReportParameterUsages) {
if (newReportParameterUsages == null) { return false; }
boolean updated = false;
if (changeInReportParameters(newReportParameterUsages)) {
updated = true;
this.reportParameterUsages.clear();
this.reportParameterUsages.addAll(newReportParameterUsages);
}
return updated;
}
private boolean changeInReportParameters(final Set<ReportParameterUsage> newReportParameterUsages) {
if (!(this.reportParameterUsages.equals(newReportParameterUsages))) { return true; }
return false;
}
public Set<ReportParameterUsage> getReportParameterUsages() {
return this.reportParameterUsages;
}
}