WIP mifosx-195 create/update validation down to domain level from json checks + put report CRUD into config bucket

This commit is contained in:
John Woodlock
2013-04-16 02:25:46 +01:00
parent cd81798270
commit c4ba4c54ca
4 changed files with 153 additions and 164 deletions
@@ -0,0 +1,2 @@
update m_permission set grouping = 'configuration' where entity_name = 'report';
@@ -5,7 +5,9 @@
*/ */
package org.mifosplatform.infrastructure.dataqueries.domain; package org.mifosplatform.infrastructure.dataqueries.domain;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.persistence.Column; import javax.persistence.Column;
@@ -15,6 +17,10 @@ import javax.persistence.UniqueConstraint;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.springframework.data.jpa.domain.AbstractPersistable; import org.springframework.data.jpa.domain.AbstractPersistable;
@Entity @Entity
@@ -50,6 +56,7 @@ public class Report extends AbstractPersistable<Long> {
* @ManyToMany * @ManyToMany
* *
* @JoinTable(name = "stretchy_report_parameter", joinColumns = * @JoinTable(name = "stretchy_report_parameter", joinColumns =
*
* @JoinColumn(name = "reportn_id"), inverseJoinColumns = @JoinColumn(name = * @JoinColumn(name = "reportn_id"), inverseJoinColumns = @JoinColumn(name =
* "parameter_id")) private List<Charge> charges; * "parameter_id")) private List<Charge> charges;
*/ */
@@ -81,8 +88,8 @@ public class Report extends AbstractPersistable<Long> {
public Report(final String reportName, final String reportType, public Report(final String reportName, final String reportType,
final String reportSubType, final String reportCategory, final String reportSubType, final String reportCategory,
final String description, final String description, final boolean useReport,
final boolean useReport, final String reportSql) { final String reportSql) {
this.reportName = reportName; this.reportName = reportName;
this.reportType = reportType; this.reportType = reportType;
this.reportSubType = reportSubType; this.reportSubType = reportSubType;
@@ -91,60 +98,149 @@ public class Report extends AbstractPersistable<Long> {
this.coreReport = false; this.coreReport = false;
this.useReport = useReport; this.useReport = useReport;
this.reportSql = reportSql; this.reportSql = reportSql;
validate();
} }
public Map<String, Object> update(final JsonCommand command) { public Map<String, Object> update(final JsonCommand command) {
final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(8); final Map<String, Object> actualChanges = new LinkedHashMap<String, Object>(
8);
String paramName = "reportName"; String paramName = "reportName";
if (command.isChangeInStringParameterNamed(paramName, this.reportName)) { if (command.isChangeInStringParameterNamed(paramName, this.reportName)) {
final String newValue = command.stringValueOfParameterNamed(paramName); final String newValue = command
actualChanges.put(paramName, newValue); .stringValueOfParameterNamed(paramName);
this.reportName = StringUtils.defaultIfEmpty(newValue, null); actualChanges.put(paramName, newValue);
} this.reportName = StringUtils.defaultIfEmpty(newValue, null);
paramName = "reportType"; }
if (command.isChangeInStringParameterNamed(paramName, this.reportType)) { paramName = "reportType";
final String newValue = command.stringValueOfParameterNamed(paramName); if (command.isChangeInStringParameterNamed(paramName, this.reportType)) {
actualChanges.put(paramName, newValue); final String newValue = command
this.reportType = StringUtils.defaultIfEmpty(newValue, null); .stringValueOfParameterNamed(paramName);
} actualChanges.put(paramName, newValue);
paramName = "reportSubType"; this.reportType = StringUtils.defaultIfEmpty(newValue, null);
if (command.isChangeInStringParameterNamed(paramName, this.reportSubType)) { }
final String newValue = command.stringValueOfParameterNamed(paramName); paramName = "reportSubType";
actualChanges.put(paramName, newValue); if (command.isChangeInStringParameterNamed(paramName,
this.reportSubType = StringUtils.defaultIfEmpty(newValue, null); this.reportSubType)) {
} final String newValue = command
paramName = "reportCategory"; .stringValueOfParameterNamed(paramName);
if (command.isChangeInStringParameterNamed(paramName, this.reportCategory)) { actualChanges.put(paramName, newValue);
final String newValue = command.stringValueOfParameterNamed(paramName); this.reportSubType = StringUtils.defaultIfEmpty(newValue, null);
actualChanges.put(paramName, newValue); }
this.reportCategory = StringUtils.defaultIfEmpty(newValue, null); paramName = "reportCategory";
} if (command.isChangeInStringParameterNamed(paramName,
paramName = "description"; this.reportCategory)) {
if (command.isChangeInStringParameterNamed(paramName, this.description)) { final String newValue = command
final String newValue = command.stringValueOfParameterNamed(paramName); .stringValueOfParameterNamed(paramName);
actualChanges.put(paramName, newValue); actualChanges.put(paramName, newValue);
this.description = StringUtils.defaultIfEmpty(newValue, null); this.reportCategory = StringUtils.defaultIfEmpty(newValue, null);
} }
paramName = "useReport"; paramName = "description";
if (command.isChangeInBooleanParameterNamed(paramName, this.useReport)) { if (command.isChangeInStringParameterNamed(paramName, this.description)) {
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(paramName); final String newValue = command
actualChanges.put(paramName, newValue); .stringValueOfParameterNamed(paramName);
this.useReport = newValue; actualChanges.put(paramName, newValue);
} this.description = StringUtils.defaultIfEmpty(newValue, null);
paramName = "reportSql"; }
if (command.isChangeInStringParameterNamed(paramName, this.reportSql)) { paramName = "useReport";
final String newValue = command.stringValueOfParameterNamed(paramName); if (command.isChangeInBooleanParameterNamed(paramName, this.useReport)) {
actualChanges.put(paramName, newValue); final boolean newValue = command
this.reportSql = StringUtils.defaultIfEmpty(newValue, null); .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);
}
return actualChanges; validate();
}
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() { public boolean isCoreReport() {
return coreReport; return coreReport;
} }
private void validate() {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
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()
.notExceedingLengthOf(20)
.isOneOfTheseValues(
new Object[] { "Table", "Pentaho", "Chart" });
baseDataValidator.reset().parameter("reportSubType")
.value(this.reportSubType).notExceedingLengthOf(20);
if (this.reportType.equals("Chart")) {
baseDataValidator
.reset()
.parameter("reportSubType")
.value(this.reportSubType)
.cantBeBlankWhenParameterProvidedIs("reportType",
this.reportType)
.isOneOfTheseValues(new Object[] { "Bar", "Pie" });
}
baseDataValidator.reset().parameter("reportCategory").value(this.reportCategory)
.notExceedingLengthOf(45);
if (this.reportType != null) {
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(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
}
} }
@@ -6,23 +6,17 @@
package org.mifosplatform.infrastructure.dataqueries.serialization; package org.mifosplatform.infrastructure.dataqueries.serialization;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@Component @Component
@@ -33,7 +27,7 @@ public final class ReportCommandFromApiJsonDeserializer {
*/ */
private final Set<String> supportedParameters = new HashSet<String>( private final Set<String> supportedParameters = new HashSet<String>(
Arrays.asList("reportName", "reportType", "reportSubType", Arrays.asList("reportName", "reportType", "reportSubType",
"reportCategory", "reportSql", "useReport")); "reportCategory", "description", "reportSql", "useReport"));
private final FromJsonHelper fromApiJsonHelper; private final FromJsonHelper fromApiJsonHelper;
@@ -43,108 +37,15 @@ public final class ReportCommandFromApiJsonDeserializer {
this.fromApiJsonHelper = fromApiJsonHelper; this.fromApiJsonHelper = fromApiJsonHelper;
} }
public void validate_for_create(final String json) { public void validate(final String json) {
validate(json, "create");
}
public void validate_for_update(final String json) {
validate(json, "update");
}
private void validate(final String json, final String commandType) {
if (StringUtils.isBlank(json)) { if (StringUtils.isBlank(json)) {
throw new InvalidJsonException(); throw new InvalidJsonException();
} }
final Type typeOfMap = new TypeToken<Map<String, Object>>() { final Type typeOfMap = new TypeToken<Map<String, Object>>() {
}.getType(); }.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json,
supportedParameters); supportedParameters);
// wip jpw
boolean isCreate = false;
if (commandType.equals("create"))
isCreate = true;
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(
dataValidationErrors).resource("report");
final JsonElement element = fromApiJsonHelper.parse(json);
String paramName = "reportName";
String paramValueStr = fromApiJsonHelper.extractStringNamed(paramName,
element);
baseDataValidator.reset().parameter(paramName).value(paramValueStr)
.notBlank().notExceedingLengthOf(100);
String paramReportType = fromApiJsonHelper.extractStringNamed(
"reportType", element);
paramName = "reportType";
paramValueStr = fromApiJsonHelper
.extractStringNamed(paramName, element);
baseDataValidator
.reset()
.parameter(paramName)
.value(paramValueStr)
.notBlank()
.notExceedingLengthOf(20)
.isOneOfTheseValues(
new Object[] { "Table", "Pentaho", "Chart" });
paramName = "reportSubType";
paramValueStr = fromApiJsonHelper
.extractStringNamed(paramName, element);
baseDataValidator.reset().parameter(paramName).value(paramValueStr)
.notExceedingLengthOf(20);
if (paramReportType != null) {
if (paramReportType.equals("Chart")) {
baseDataValidator
.reset()
.parameter(paramName)
.value(paramValueStr)
.cantBeBlankWhenParameterProvidedIs("reportType",
paramReportType)
.isOneOfTheseValues(new Object[] { "Bar", "Pie" });
}
}
paramName = "reportCategory";
paramValueStr = fromApiJsonHelper
.extractStringNamed(paramName, element);
baseDataValidator.reset().parameter(paramName).value(paramValueStr)
.notExceedingLengthOf(45);
paramName = "reportSql";
paramValueStr = fromApiJsonHelper
.extractStringNamed(paramName, element);
if (paramReportType != null) {
if ((paramReportType.equals("Table"))
|| (paramReportType.equals("Chart"))) {
baseDataValidator
.reset()
.parameter(paramName)
.value(paramValueStr)
.cantBeBlankWhenParameterProvidedIs("reportType",
paramReportType);
} else {
baseDataValidator
.reset()
.parameter(paramName)
.value(paramValueStr)
.mustBeBlankWhenParameterProvidedIs("reportType",
paramReportType);
}
}
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(
final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) {
throw new PlatformApiDataValidationException(
"validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors);
}
} }
} }
@@ -51,7 +51,7 @@ public class ReportWritePlatformServiceImpl implements
try { try {
context.authenticatedUser(); context.authenticatedUser();
this.fromApiJsonDeserializer.validate_for_create(command.json()); this.fromApiJsonDeserializer.validate(command.json());
final Report report = Report.fromJson(command); final Report report = Report.fromJson(command);
@@ -74,7 +74,7 @@ public class ReportWritePlatformServiceImpl implements
try { try {
context.authenticatedUser(); context.authenticatedUser();
this.fromApiJsonDeserializer.validate_for_update(command.json()); this.fromApiJsonDeserializer.validate(command.json());
final Report report = this.reportRepository.findOne(reportId); final Report report = this.reportRepository.findOne(reportId);
if (report == null) { if (report == null) {
@@ -83,16 +83,6 @@ public class ReportWritePlatformServiceImpl implements
final Map<String, Object> changes = report.update(command); final Map<String, Object> changes = report.update(command);
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
if (report.isCoreReport()) {
for (final String key : changes.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);
}
}
}
this.reportRepository.saveAndFlush(report); this.reportRepository.saveAndFlush(report);
} }