[New] Added REST API for Reports

This commit is contained in:
Robert von Burg 2018-09-07 10:17:37 +02:00
parent 966fbf6f69
commit 9b8e91d0a5
17 changed files with 533 additions and 73 deletions

View File

@ -1,12 +1,12 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
*
* Licensed 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.
@ -56,6 +56,10 @@ public class StrolchModelConstants {
* This uom value indicates that the {@link Parameter} has no defined uom
*/
public static final String UOM_NONE = "None"; //$NON-NLS-1$
public static final String INTERNAL = "internal";
public static final String SUFFIX_REF = "-Ref";
public static final String BAG_RELATIONS = "relations";
public static final String BAG_PARAMETERS = "parameters";
}

View File

@ -15,7 +15,9 @@
*/
package li.strolch.model;
@SuppressWarnings("nls")
/**
* This class contains all constants used to marshall strolch objects to XML and JSON.
*/
public class Tags {
public static final String AGENT = "Agent";

View File

@ -50,6 +50,12 @@
<artifactId>javax.mail-api</artifactId>
</dependency>
<!-- utils -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
</dependency>
<!-- Web -->
<dependency>
<groupId>javax.servlet</groupId>

View File

@ -38,6 +38,7 @@ public class StrolchRestfulClasses {
restfulClasses.add(AuthenticationService.class);
restfulClasses.add(StrolchJobsResource.class);
restfulClasses.add(ReportResource.class);
restfulClasses.add(Inspector.class);
restfulClasses.add(VersionQuery.class);
restfulClasses.add(ModelQuery.class);

View File

@ -1,12 +1,12 @@
/*
* Copyright 2013 Robert von Burg <eitch@eitchnet.ch>
*
*
* Licensed 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.
@ -15,6 +15,8 @@
*/
package li.strolch.rest;
import javax.ws.rs.core.MediaType;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
@ -34,4 +36,14 @@ public class StrolchRestfulConstants {
public static final String OFFSET = "offset";
public static final String LIMIT = "limit";
public static final String PARAM_DATE_RANGE = "dateRange";
public static final String PARAM_DATE_RANGE_SEL = "dateRangeSel";
public static final String PARAM_FACETS = "facets";
public static final String PARAM_FROM = "from";
public static final String PARAM_TO = "to";
public static final String PARAM_FILTER = "filter";
public static final String PARAM_QUERY = "query";
public static final MediaType TEXT_CSV_TYPE = new MediaType("text", "csv");
public static final String TEXT_CSV = "text/csv";
}

View File

@ -0,0 +1,412 @@
package li.strolch.rest.endpoint;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static li.strolch.report.ReportConstants.*;
import static li.strolch.rest.StrolchRestfulConstants.*;
import static li.strolch.rest.StrolchRestfulConstants.PARAM_DATE_RANGE_SEL;
import static li.strolch.utils.helper.StringHelper.formatNanoDuration;
import static li.strolch.utils.helper.StringHelper.isNotEmpty;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import li.strolch.model.Resource;
import li.strolch.model.StrolchRootElement;
import li.strolch.model.Tags;
import li.strolch.model.parameter.StringParameter;
import li.strolch.persistence.api.StrolchTransaction;
import li.strolch.privilege.model.Certificate;
import li.strolch.report.Report;
import li.strolch.report.ReportSearch;
import li.strolch.rest.RestfulStrolchComponent;
import li.strolch.rest.StrolchRestfulConstants;
import li.strolch.rest.helper.ResponseUtil;
import li.strolch.utils.collections.DateRange;
import li.strolch.utils.collections.MapOfSets;
import li.strolch.utils.dbc.DBC;
import li.strolch.utils.helper.StringHelper;
import li.strolch.utils.iso8601.ISO8601FormatFactory;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Path("strolch/reports")
public class ReportResource {
private static final Logger logger = LoggerFactory.getLogger(ReportResource.class);
private static String getContext() {
StackTraceElement element = new Throwable().getStackTrace()[1];
return element.getClassName() + "." + element.getMethodName();
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllReportIds(@Context HttpServletRequest request) {
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
List<Resource> ids = new ReportSearch().search(tx).orderByName(false).toList();
// create final array
JsonArray array = new JsonArray();
ids.forEach(res -> {
JsonObject o = new JsonObject();
o.addProperty(Tags.Json.ID, res.getId());
o.addProperty(Tags.Json.NAME, res.getName());
o.addProperty(PARAM_DATE_RANGE, res.hasParameter(BAG_PARAMETERS, PARAM_DATE_RANGE_SEL));
array.add(o);
});
return ResponseUtil.toResponse(DATA, array);
}
}
@GET
@Path("{id}/facets")
@Produces(MediaType.APPLICATION_JSON)
public Response getReportFacets(@Context HttpServletRequest request, @PathParam("id") String id,
@QueryParam(LIMIT) String limitS) throws IOException {
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
int limit = isNotEmpty(limitS) ? Integer.parseInt(limitS) : 10;
File localesF = new File(request.getServletContext().getRealPath(LOCALES_JSON));
JsonObject localeJ = null;
if (localesF.exists()) {
JsonObject localesJ = new JsonParser().parse(new String(Files.readAllBytes(localesF.toPath())))
.getAsJsonObject();
if (localesJ.has(cert.getLocale().toString()))
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
JsonArray result = new JsonArray();
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
MapOfSets<String, StrolchRootElement> criteria = report.generateFilterCriteria();
criteria.keySet().forEach(type -> {
JsonArray values = new JsonArray();
criteria.getSet(type).stream().limit(limit) //
.forEach(f -> {
JsonObject o = new JsonObject();
o.addProperty(Tags.Json.ID, f.getId());
o.addProperty(Tags.Json.NAME, f.getName());
values.add(o);
});
JsonObject filter = new JsonObject();
filter.addProperty(Tags.Json.TYPE, type);
filter.add(Tags.Json.VALUES, values);
result.add(filter);
});
return ResponseUtil.toResponse(DATA, result);
}
}
@GET
@Path("{id}/facets/{type}/fields")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getReportFacetValues(@Context HttpServletRequest request, @PathParam("id") String id,
@PathParam("type") String type, @QueryParam(PARAM_QUERY) String queryS, @QueryParam(LIMIT) String limitS)
throws IOException {
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
String query = isNotEmpty(queryS) ? queryS.toLowerCase() : queryS;
int limit = isNotEmpty(limitS) ? Integer.parseInt(limitS) : 10;
File localesF = new File(request.getServletContext().getRealPath(LOCALES_JSON));
JsonObject localeJ = null;
if (localesF.exists()) {
JsonObject localesJ = new JsonParser().parse(new String(Files.readAllBytes(localesF.toPath())))
.getAsJsonObject();
if (localesJ.has(cert.getLocale().toString()))
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
// get report
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
// get filter criteria
MapOfSets<String, StrolchRootElement> criteria = report.generateFilterCriteria();
// create final array
JsonArray array = new JsonArray();
Set<StrolchRootElement> valueSet = criteria.getSet(type);
// filter if required
if (valueSet != null) {
Stream<StrolchRootElement> stream = valueSet.stream();
if (query != null)
stream = stream.filter(f -> f.getName().toLowerCase().startsWith(query));
// limit
stream.limit(limit) //
// add the data finally
.forEach(f -> {
JsonObject o = new JsonObject();
o.addProperty(Tags.Json.ID, f.getId());
o.addProperty(Tags.Json.NAME, f.getName());
array.add(o);
});
}
return ResponseUtil.toResponse(DATA, array);
}
}
@POST
@Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response getReportById(@Context HttpServletRequest request, @PathParam("id") String id, String data)
throws IOException {
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
DBC.PRE.assertNotEmpty("report ID is required", id);
// get information from body
JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
int offset = jsonObject.get(OFFSET) != null ? jsonObject.get(OFFSET).getAsInt() : 50;
int limit = jsonObject.get(LIMIT) != null ? jsonObject.get(LIMIT).getAsInt() : 50;
MapOfSets<String, String> filters = jsonObject.get(PARAM_FILTER) != null ?
getFiltersFromJson(jsonObject.get(PARAM_FILTER).getAsJsonArray()) :
new MapOfSets<>();
// get date range if defined
JsonObject rangeJ =
jsonObject.get(PARAM_DATE_RANGE) != null ? jsonObject.getAsJsonObject(PARAM_DATE_RANGE) : null;
String fromS = rangeJ != null && rangeJ.get(PARAM_FROM) != null && !rangeJ.get(PARAM_FROM).isJsonNull() ?
rangeJ.get(PARAM_FROM).getAsString() :
null;
Date from;
try {
from = fromS != null ? ISO8601FormatFactory.getInstance().parseDate(fromS) : null;
} catch (Exception e) {
logger.error("Could not parse 'from' date, setting it to null.", e);
from = null;
}
String toS = rangeJ != null && rangeJ.get(PARAM_TO) != null && !rangeJ.get(PARAM_TO).isJsonNull() ?
rangeJ.get(PARAM_TO).getAsString() :
null;
Date to;
try {
to = (toS != null) ? ISO8601FormatFactory.getInstance().parseDate(toS) : null;
} catch (Exception e) {
logger.error("Could not parse 'to' date, setting it to null.", e);
to = null;
}
File localesF = new File(request.getServletContext().getRealPath(LOCALES_JSON));
JsonObject localeJ = null;
if (localesF.exists()) {
JsonObject localesJ = new JsonParser().parse(new String(Files.readAllBytes(localesF.toPath())))
.getAsJsonObject();
if (localesJ.has(cert.getLocale().toString()))
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
long start = System.nanoTime();
// get report
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
// add filters from request
if (report.hasDateRangeSelector()) {
DateRange dateRange = new DateRange().from(from, true).to(to, true);
report.dateRange(dateRange);
}
filters.keySet().forEach(f -> report.filter(f, filters.getSet(f)));
// get rows
Stream<JsonObject> json = report.doReportAsJson().skip(offset).limit(limit);
// add rows to response
JsonObject finalResult = new JsonObject();
JsonArray rows = new JsonArray();
json.forEach(rows::add);
finalResult.add(PARAM_ROWS, rows);
// add column information to JSON
JsonArray col = new JsonArray();
Resource reportR = tx.getResourceBy(TYPE_REPORT, id, true);
reportR.getParameterBag(BAG_COLUMNS).getParameterKeySet().forEach(s -> {
StringParameter param = reportR.getParameter(BAG_COLUMNS, s, true);
JsonObject o = new JsonObject();
o.addProperty(Tags.Json.ID, s);
o.addProperty(Tags.Json.NAME, param.getName());
o.addProperty(Tags.Json.INDEX, param.getIndex());
col.add(o);
});
finalResult.add(PARAM_COLUMNS, col);
long size = report.getCounter();
long lastOffset = size % limit == 0 ? size - limit : (size / limit) * limit;
long nextOffset = Math.min(lastOffset, limit + offset);
long previousOffset = Math.max(0, offset - limit);
finalResult.addProperty(LIMIT, limit);
finalResult.addProperty(OFFSET, offset);
finalResult.addProperty(SIZE, size);
finalResult.addProperty(LAST_OFFSET, lastOffset);
finalResult.addProperty(NEXT_OFFSET, nextOffset);
finalResult.addProperty(PREVIOUS_OFFSET, previousOffset);
String duration = formatNanoDuration(System.nanoTime() - start);
finalResult.addProperty(PARAM_DURATION, duration);
logger.info(id + " Report took: " + duration);
return ResponseUtil.toResponse(DATA, finalResult);
}
}
@POST
@Path("{id}/csv")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(TEXT_CSV)
public Response getReportByIdAsCsv(@Context HttpServletRequest request, @PathParam("id") String id, String data)
throws IOException {
Certificate cert = (Certificate) request.getAttribute(StrolchRestfulConstants.STROLCH_CERTIFICATE);
DBC.PRE.assertNotEmpty("report ID is required", id);
// get information from body
JsonObject jsonObject = StringHelper.isEmpty(data) ? null : new JsonParser().parse(data).getAsJsonObject();
MapOfSets<String, String> filters = jsonObject != null && jsonObject.get(PARAM_FILTER) != null ?
getFiltersFromJson(jsonObject.get(PARAM_FILTER).getAsJsonArray()) :
new MapOfSets<>();
File localesF = new File(request.getServletContext().getRealPath(LOCALES_JSON));
JsonObject localeJ = null;
if (localesF.exists()) {
JsonObject localesJ = new JsonParser().parse(new String(Files.readAllBytes(localesF.toPath())))
.getAsJsonObject();
if (localesJ.has(cert.getLocale().toString()))
localeJ = localesJ.get(cert.getLocale().toString()).getAsJsonObject();
}
try (StrolchTransaction tx = RestfulStrolchComponent.getInstance().openTx(cert, getContext())) {
// get report
Report report = new Report(tx, id);
// set i18n data if possible
if (localeJ != null)
report.getReportPolicy().setI18nData(localeJ);
// add filters from request
filters.keySet().forEach(f -> report.filter(f, filters.getSet(f)));
// get headers
List<String> orderedColumnKeys = report.getColumnKeys();
String[] headers = new String[orderedColumnKeys.size()];
orderedColumnKeys.toArray(headers);
if (localeJ != null) {
for (int i = 0; i < headers.length; i++) {
if (localeJ.has(headers[i]))
headers[i] = localeJ.get(headers[i]).getAsString();
}
}
// create CSV printer with header
StreamingOutput out = getOut(report, headers);
// send
String fileName = id + "_" + System.currentTimeMillis() + ".csv";
return Response.ok(out, TEXT_CSV_TYPE)
.header("Content-Disposition", "attachment; filename=\"" + fileName + "\"").build();
}
}
private StreamingOutput getOut(Report report, String[] headers) {
return out -> {
// get report content and add to the buffer
try (CSVPrinter csvP = new CSVPrinter(new OutputStreamWriter(out),
CSVFormat.DEFAULT.withHeader(headers).withDelimiter(';'))) {
report.doReport().forEach(row -> {
try {
csvP.printRecord(row.valueStream().collect(Collectors.toList())); // add to CSV
} catch (Exception e) {
logger.error("Could not write CSV row", e);
}
});
}
};
}
private MapOfSets<String, String> getFiltersFromJson(JsonArray filters) {
MapOfSets<String, String> result = new MapOfSets<>();
if (filters == null) {
return result;
}
// go through all filters and add to the map of sets
for (JsonElement elem : filters.getAsJsonArray()) {
if (!elem.isJsonObject()) {
logger.warn("There are wrong formated filters:\n" + elem.toString());
continue;
}
JsonObject filter = elem.getAsJsonObject();
filter.get(PARAM_FACET_FILTERS).getAsJsonArray()
.forEach(f -> result.addElement(filter.get(PARAM_FACET_TYPE).getAsString(), f.getAsString()));
}
return result;
}
}

View File

@ -1,5 +1,7 @@
package li.strolch.execution.policy;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.exception.StrolchModelException;
import li.strolch.model.Locator;
@ -29,7 +31,6 @@ import li.strolch.persistence.api.StrolchTransaction;
public class ReservationExection extends DurationExecution {
public static final String PARAM_RESERVED = "reserved";
public static final String BAG_PARAMETERS = "parameters";
public static final String TYPE_RESERVE = "Reserve";
public static final String TYPE_RELEASE = "Release";

View File

@ -15,6 +15,8 @@
*/
package li.strolch.migrations;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import java.io.File;
import li.strolch.agent.api.ComponentContainer;

View File

@ -1,12 +1,12 @@
/*
* Copyright 2015 Robert von Burg <eitch@eitchnet.ch>
*
*
* Licensed 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.
@ -15,11 +15,8 @@
*/
package li.strolch.migrations;
import static li.strolch.migrations.Migration.BAG_PARAMETERS;
import static li.strolch.migrations.Migration.MIGRATIONS_ID;
import static li.strolch.migrations.Migration.MIGRATIONS_TYPE;
import static li.strolch.migrations.Migration.PARAM_CURRENT_DATA_VERSION;
import static li.strolch.migrations.Migration.PARAM_CURRENT_CODE_VERSION;
import static li.strolch.migrations.Migration.*;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import java.util.HashMap;
import java.util.Map;
@ -38,9 +35,6 @@ public class CurrentMigrationVersionQuery {
private ComponentContainer container;
private Map<String, MigrationVersion> currentVersions;
/**
* @param container
*/
public CurrentMigrationVersionQuery(ComponentContainer container) {
this.container = container;
}
@ -56,47 +50,45 @@ public class CurrentMigrationVersionQuery {
Resource migrationsRes = tx.getResourceBy(MIGRATIONS_TYPE, MIGRATIONS_ID);
if (migrationsRes == null) {
this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion));
this.currentVersions
.put(realmName, new MigrationVersion(Version.emptyVersion, Version.emptyVersion));
continue;
}
StringParameter currentDataVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION);
StringParameter currentCodeVersionP = migrationsRes.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION);
StringParameter currentDataVersionP = migrationsRes
.getParameter(BAG_PARAMETERS, PARAM_CURRENT_DATA_VERSION);
StringParameter currentCodeVersionP = migrationsRes
.getParameter(BAG_PARAMETERS, PARAM_CURRENT_CODE_VERSION);
if (currentDataVersionP == null && currentCodeVersionP == null) {
this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,Version.emptyVersion));
} else if(currentDataVersionP == null && currentCodeVersionP != null) {
this.currentVersions
.put(realmName, new MigrationVersion(Version.emptyVersion, Version.emptyVersion));
} else if (currentDataVersionP == null) {
Version codeVersion = getVersionFromParam(currentCodeVersionP);
this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion,codeVersion));
} else if (currentDataVersionP != null && currentCodeVersionP == null) {
this.currentVersions.put(realmName, new MigrationVersion(Version.emptyVersion, codeVersion));
} else if (currentCodeVersionP == null) {
Version dataVersion = getVersionFromParam(currentDataVersionP);
this.currentVersions.put(realmName, new MigrationVersion(dataVersion,Version.emptyVersion));
this.currentVersions.put(realmName, new MigrationVersion(dataVersion, Version.emptyVersion));
} else {
Version dataVersion = getVersionFromParam(currentDataVersionP);
Version codeVersion = getVersionFromParam(currentCodeVersionP);
this.currentVersions.put(realmName, new MigrationVersion(dataVersion,codeVersion));
this.currentVersions.put(realmName, new MigrationVersion(dataVersion, codeVersion));
}
}
}
}
/**
* @param versionS
* @return
*/
private Version getVersionFromParam(StringParameter versionP) {
String versionS = versionP.getValue();
if (!Version.isParseable(versionS)) {
throw new StrolchConfigurationException("Version value " + versionS + " is not valid for "
+ versionP.getLocator());
throw new StrolchConfigurationException(
"Version value " + versionS + " is not valid for " + versionP.getLocator());
}
Version version = Version.valueOf(versionS);
return version;
return Version.valueOf(versionS);
}
public Map<String, MigrationVersion> getCurrentVersions() {
return this.currentVersions;
}
}

View File

@ -15,6 +15,8 @@
*/
package li.strolch.migrations;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import java.io.File;
import java.text.MessageFormat;
import java.util.Collections;

View File

@ -15,6 +15,8 @@
*/
package li.strolch.migrations;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import java.io.File;
import li.strolch.agent.api.ComponentContainer;
@ -31,7 +33,6 @@ public abstract class Migration {
public static final String MIGRATIONS_TYPE = "Migrations";
public static final String MIGRATIONS_ID = "migrations";
public static final String BAG_PARAMETERS = "parameters";
public static final String PARAM_CURRENT_DATA_VERSION = "currentDataVersion";
public static final String PARAM_CURRENT_CODE_VERSION = "currentCodeVersion";

View File

@ -5,9 +5,7 @@ public class ReportConstants {
public static final String TYPE_REPORT = "Report";
public static final String TYPE_FILTER = "Filter";
public static final String BAG_RELATIONS = "relations";
public static final String BAG_JOINS = "joins";
public static final String BAG_PARAMETERS = "parameters";
public static final String BAG_COLUMNS = "columns";
public static final String BAG_ORDERING = "ordering";
@ -15,8 +13,14 @@ public class ReportConstants {
public static final String PARAM_DESCENDING = "descending";
public static final String PARAM_DATE_RANGE_SEL = "dateRangeSel";
public static final String PARAM_FIELD_REF = "fieldRef";
public static final String PARAM_POLICY = "policy";
public static final String PARAM_ALLOW_MISSING_COLUMNS = "allowMissingColumns";
public static final String PARAM_POLICY = "policy";
public static final String PARAM_COLUMNS = "columns";
public static final String PARAM_ROWS = "rows";
public static final String PARAM_DURATION = "duration";
public static final String PARAM_FACET_FILTERS = "facetFilters";
public static final String PARAM_FACET_TYPE = "facetType";
public static final String COL_OBJECT = "$object";
public static final String COL_ID = "$id";
@ -26,8 +30,7 @@ public class ReportConstants {
public static final String COL_DATE = "$date";
public static final String COL_SEARCH = "$search";
public static final String LOCALES_JSON = "locales.json";
public static final String SEARCH_SEPARATOR = ":";
public static final String SUFFIX_REF = "-Ref";
}

View File

@ -0,0 +1,17 @@
package li.strolch.report;
import static li.strolch.report.ReportConstants.TYPE_REPORT;
import li.strolch.search.ResourceSearch;
/**
* Query to get report resources
*
* @author mvoigt
*/
public class ReportSearch extends ResourceSearch {
public ReportSearch() {
types(TYPE_REPORT);
}
}

View File

@ -1,6 +1,7 @@
package li.strolch.report.policy;
import static java.util.Comparator.comparingInt;
import static li.strolch.model.StrolchModelConstants.*;
import static li.strolch.report.ReportConstants.*;
import static li.strolch.utils.helper.StringHelper.EMPTY;
@ -10,6 +11,7 @@ import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.gson.JsonObject;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.model.*;
import li.strolch.model.parameter.AbstractParameter;
@ -39,8 +41,6 @@ public class GenericReport extends ReportPolicy {
private Resource reportRes;
private String objectType;
private ParameterBag columnsBag;
private List<StringParameter> orderingParams;
private Map<String, StringParameter> filterCriteriaParams;
@ -55,13 +55,15 @@ public class GenericReport extends ReportPolicy {
private long counter;
protected JsonObject i18nData;
public GenericReport(ComponentContainer container, StrolchTransaction tx) {
super(container, tx);
}
/**
* Retrieves the <code>Resource</code> with the given ID, and initializes this instance with the data specified on
* the report
* Retrieves the {@code Resource} with the given ID, and initializes this instance with the data specified on the
* report
*
* @param reportId
* the report to use
@ -72,7 +74,7 @@ public class GenericReport extends ReportPolicy {
this.reportRes = tx().getResourceBy(TYPE_REPORT, reportId, true);
StringParameter objectTypeP = this.reportRes.getParameter(BAG_PARAMETERS, PARAM_OBJECT_TYPE);
this.objectType = objectTypeP.getValue();
String objectType = objectTypeP.getValue();
this.columnsBag = this.reportRes.getParameterBag(BAG_COLUMNS, true);
@ -92,8 +94,8 @@ public class GenericReport extends ReportPolicy {
// evaluate filter criteria params
this.filterCriteriaParams = new HashMap<>();
StringParameter objectTypeFilterCriteriaP = objectTypeP.getClone();
objectTypeFilterCriteriaP.setId(this.objectType);
this.filterCriteriaParams.put(this.objectType, objectTypeFilterCriteriaP);
objectTypeFilterCriteriaP.setId(objectType);
this.filterCriteriaParams.put(objectType, objectTypeFilterCriteriaP);
if (this.reportRes.hasParameterBag(BAG_JOINS)) {
ParameterBag joinBag = this.reportRes.getParameterBag(BAG_JOINS);
joinBag.getParameters()
@ -127,6 +129,10 @@ public class GenericReport extends ReportPolicy {
}
}
public void setI18nData(JsonObject i18nData) {
this.i18nData = i18nData;
}
public long getCounter() {
return this.counter;
}
@ -134,7 +140,7 @@ public class GenericReport extends ReportPolicy {
/**
* Returns true if the report has a date range selector specified
*
* @return
* @return true if the report has a date range selector specified
*/
public boolean hasDateRangeSelector() {
return this.dateRangeSelP != null;

View File

@ -5,6 +5,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import com.google.gson.JsonObject;
import li.strolch.agent.api.ComponentContainer;
import li.strolch.model.StrolchRootElement;
import li.strolch.persistence.api.StrolchTransaction;
@ -19,6 +20,8 @@ public abstract class ReportPolicy extends StrolchPolicy {
super(container, tx);
}
public abstract void setI18nData(JsonObject i18nData);
public abstract void initialize(String reportId);
public abstract boolean hasDateRangeSelector();

View File

@ -1,16 +1,11 @@
package li.strolch.execution;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static li.strolch.execution.policy.ReservationExection.PARAM_RESERVED;
import static li.strolch.model.StrolchModelConstants.BAG_PARAMETERS;
import static org.junit.Assert.*;
import java.io.File;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import li.strolch.execution.policy.ReservationExection;
import li.strolch.execution.service.StartActivityExecutionService;
import li.strolch.model.Locator;
import li.strolch.model.Resource;
@ -25,6 +20,9 @@ import li.strolch.service.LocatorArgument;
import li.strolch.service.parameter.SetParameterService;
import li.strolch.service.parameter.SetParameterService.SetParameterArg;
import li.strolch.testbase.runtime.RuntimeMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ReservationExecutionTest extends RuntimeMock {
@ -50,8 +48,8 @@ public class ReservationExecutionTest extends RuntimeMock {
// before we execute, we reserve, so execution can't be done
SetParameterService setParamSvc = new SetParameterService();
SetParameterArg setParamArg = new SetParameterArg();
setParamArg.locator = Locator.valueOf(Tags.RESOURCE, "Machine", "machine1", Tags.BAG,
ReservationExection.BAG_PARAMETERS, ReservationExection.PARAM_RESERVED);
setParamArg.locator = Locator
.valueOf(Tags.RESOURCE, "Machine", "machine1", Tags.BAG, BAG_PARAMETERS, PARAM_RESERVED);
setParamArg.valueAsString = "true";
doServiceAssertResult(cert, setParamSvc, setParamArg);
@ -84,8 +82,7 @@ public class ReservationExecutionTest extends RuntimeMock {
// verify that the machine is not reserved
Resource machine = tx.getResourceBy("Machine", "machine1");
BooleanParameter reservedP = machine.getParameter(ReservationExection.BAG_PARAMETERS,
ReservationExection.PARAM_RESERVED);
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
assertFalse(reservedP.getValue());
}
@ -107,8 +104,7 @@ public class ReservationExecutionTest extends RuntimeMock {
// verify that the machine is reserved
Resource machine = tx.getResourceBy("Machine", "machine1");
BooleanParameter reservedP = machine.getParameter(ReservationExection.BAG_PARAMETERS,
ReservationExection.PARAM_RESERVED);
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
assertTrue(reservedP.getValue());
}
@ -123,8 +119,7 @@ public class ReservationExecutionTest extends RuntimeMock {
// verify that the machine is not reserved anymore
Resource machine = tx.getResourceBy("Machine", "machine1");
BooleanParameter reservedP = machine.getParameter(ReservationExection.BAG_PARAMETERS,
ReservationExection.PARAM_RESERVED);
BooleanParameter reservedP = machine.getParameter(BAG_PARAMETERS, PARAM_RESERVED);
assertFalse(reservedP.getValue());
}
}

View File

@ -87,6 +87,7 @@
<javaxmail.version>1.6.0</javaxmail.version>
<serverlet.version>3.1.0</serverlet.version>
<jaxrs.api.version>2.1</jaxrs.api.version>
<csv.version>1.4</csv.version>
<junit.version>4.12</junit.version>
<hamcrest.version>1.3</hamcrest.version>
@ -219,9 +220,9 @@
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.github.petitparser.java-petitparser</groupId>
<artifactId>petitparser-core</artifactId>
<version>${petitparser.version}</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>${csv.version}</version>
</dependency>
<!-- Database -->