package com.constellio.model.services.reports;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from;
import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.where;
import java.util.ArrayList;
import java.util.List;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.Transaction;
import com.constellio.model.entities.records.wrappers.Report;
import com.constellio.model.entities.records.wrappers.User;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataSchema;
import com.constellio.model.entities.schemas.MetadataSchemaTypes;
import com.constellio.model.entities.schemas.Schemas;
import com.constellio.model.services.factories.ModelLayerFactory;
import com.constellio.model.services.records.RecordServices;
import com.constellio.model.services.records.RecordServicesException;
import com.constellio.model.services.search.SearchServices;
import com.constellio.model.services.search.query.ReturnedMetadatasFilter;
import com.constellio.model.services.search.query.logical.LogicalSearchQuery;
import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition;
import com.constellio.model.services.users.UserServicesRuntimeException;
public class ReportServices {
private final MetadataSchema reportSchema;
private final String collection;
SearchServices searchServices;
RecordServices recordServices;
private ModelLayerFactory modelLayerFactory;
public ReportServices(ModelLayerFactory modelLayerFactory, String collection) {
this.searchServices = modelLayerFactory.newSearchServices();
this.recordServices = modelLayerFactory.newRecordServices();
this.modelLayerFactory = modelLayerFactory;
this.collection = collection;
MetadataSchemaTypes schemaTypes = modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection);
reportSchema = schemaTypes.getSchema(Report.DEFAULT_SCHEMA);
}
public void deleteReport(User user, Report report)
{
String reportUsername = report.getUsername();
if (user.getUsername().equals(reportUsername)) {
delete(report, user);
} else {
if (report.getUsername() == null || hasReportManagementPermission(user)
&& recordServices.isLogicallyThenPhysicallyDeletable(report.getWrappedRecord(), user)) {
delete(report, user);
} else {
throw new CouldNotDeleteSomeoneElseReportRuntimeException(report.getUsername() + "!=" + user.getUsername());
}
}
}
public void saveReport(User user, Report report) {
String reportUsername = report.getUsername();
if (user.getUsername().equals(reportUsername)) {
addUpdate(report);
} else {
if (report.getUsername() == null || hasReportManagementPermission(user)) {
addUpdate(report);
} else {
throw new CouldNotModifySomeoneElseReportRuntimeException(report.getUsername() + "!=" + user.getUsername());
}
}
}
private boolean hasReportManagementPermission(User user) {
//TODO
return true;
}
public List<Report> getUserReports(User user, String schemaTypeCode) {
Metadata schemaTypeCodeMetadata = reportSchema.getMetadata(Report.SCHEMA_TYPE_CODE);
Metadata userMetaData = reportSchema.getMetadata(Report.USERNAME);
LogicalSearchQuery query = new LogicalSearchQuery();
String username = null;
if (user != null) {
username = user.getUsername();
}
query.setCondition(
from(reportSchema).where(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode)
.andWhere(userMetaData).isEqualTo(username));
List<Record> results = searchServices.search(query);
return wrapReports(results);
}
private List<Report> wrapReports(List<Record> records) {
List<Report> reports = new ArrayList<>();
for (Record record : records) {
reports.add(new Report(record, modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection)));
}
return reports;
}
public Report getReport(String schemaTypeCode, String reportTitle) {
return getUserReport(null, schemaTypeCode, reportTitle);
}
public Report getUserReport(String username, String schemaTypeCode, String reportTitle) {
Metadata schemaTypeCodeMetadata = reportSchema.getMetadata(Report.SCHEMA_TYPE_CODE);
Metadata userMetadata = reportSchema.getMetadata(Report.USERNAME);
Metadata titleMetaData = Schemas.TITLE;
LogicalSearchQuery query = new LogicalSearchQuery();
if (username != null) {
query.setCondition(from(reportSchema)
.where(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode)
.andWhere(userMetadata).isEqualTo(username)
.andWhere(titleMetaData).isEqualTo(reportTitle));
} else {
query.setCondition(from(reportSchema)
.where(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode)
.andWhere(userMetadata).isNull()
.andWhere(titleMetaData).isEqualTo(reportTitle));
}
long count = searchServices.getResultsCount(query);
if (count == 0) {
if (username == null) {
return null;
} else {
query.setCondition(from(reportSchema)
.where(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode)
.andWhere(userMetadata).isNull()
.andWhere(titleMetaData).isEqualTo(reportTitle));
if (searchServices.getResultsCount(query) == 0) {
return null;
}
}
}
List<Record> results = searchServices.search(query);
return new Report(results.get(0), modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection));
}
public List<Report> getReports(String schemaTypeCode) {
Metadata schemaTypeCodeMetadata = reportSchema.getMetadata(Report.SCHEMA_TYPE_CODE);
Metadata userMetadata = reportSchema.getMetadata(Report.USERNAME);
LogicalSearchQuery query = new LogicalSearchQuery();
query.setCondition(from(reportSchema)
.where(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode)
.andWhere(userMetadata).isNull());
long count = searchServices.getResultsCount(query);
if (count == 0) {
return new ArrayList<>();
} else {
List<Record> results = searchServices.search(query);
MetadataSchemaTypes types = modelLayerFactory.getMetadataSchemasManager().getSchemaTypes(collection);
return warpReports(results, types);
}
}
private List<Report> warpReports(List<Record> results, MetadataSchemaTypes types) {
List<Report> returnList = new ArrayList<>();
for (Record record : results) {
returnList.add(new Report(record, types));
}
return returnList;
}
public void delete(Report report, User user)
{
recordServices.logicallyDelete(report.getWrappedRecord(), user);
recordServices.physicallyDelete(report.getWrappedRecord(), user);
}
public void addUpdate(Report report) {
Transaction transaction = new Transaction();
transaction.add(report);
try {
recordServices.execute(transaction);
} catch (RecordServicesException e) {
throw new UserServicesRuntimeException.UserServicesRuntimeException_CannotExcuteTransaction(e);
}
}
public List<String> getUserReportTitles(User user, String schemaTypeCode) {
List<String> returnList = new ArrayList<>();
Metadata schemaTypeCodeMetadata = reportSchema.getMetadata(Report.SCHEMA_TYPE_CODE);
Metadata userMetadata = reportSchema.getMetadata(Report.USERNAME);
Metadata titleMetaData = reportSchema.getMetadata(Report.TITLE);
LogicalSearchQuery query = new LogicalSearchQuery();
LogicalSearchCondition withUserNameOrWithNull;
if (user != null) {
withUserNameOrWithNull = where(userMetadata).isEqualTo(user.getUsername()).orWhere(userMetadata).isNull();
} else {
withUserNameOrWithNull = where(userMetadata).isNull();
}
query.setCondition(
from(reportSchema).where(withUserNameOrWithNull).andWhere(schemaTypeCodeMetadata).isEqualTo(schemaTypeCode));
long count = searchServices.getResultsCount(query);
if (count == 0) {
return returnList;
}
query.setReturnedMetadatas(ReturnedMetadatasFilter.idVersionSchemaTitle());
List<Record> results = searchServices.search(query);
if (results == null || results.isEmpty()) {
return returnList;
}
for (Record record : results) {
String reportTitle = record.get(titleMetaData);
returnList.add(reportTitle);
}
return returnList;
}
private class CouldNotModifySomeoneElseReportRuntimeException extends RuntimeException {
public CouldNotModifySomeoneElseReportRuntimeException(String message) {
super(message);
}
}
private class CouldNotDeleteSomeoneElseReportRuntimeException extends RuntimeException {
public CouldNotDeleteSomeoneElseReportRuntimeException(String message) {
super(message);
}
}
}