363 lines
18 KiB
HTML
363 lines
18 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="google-site-verification" content="CPhbjooaiTdROm7Vs4E7kuHZvBfkeLUtonGgcVUbTL8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="description" content="">
|
|
<meta name="author" content="">
|
|
<link rel="shortcut icon" href="ico/favicon.ico">
|
|
|
|
<title>Strolch: Reports</title>
|
|
|
|
<!-- Bootstrap core CSS -->
|
|
<link href="css/bootstrap.min.css" rel="stylesheet">
|
|
|
|
<!-- Custom styles for this template -->
|
|
<link href="css/custom.css" rel="stylesheet">
|
|
|
|
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --><!--[if lt IE 9]>
|
|
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
|
|
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script><![endif]-->
|
|
</head>
|
|
<body>
|
|
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
|
<div class="container">
|
|
<div class="navbar-header">
|
|
<a class="navbar-brand" href="index.html">Strolch</a>
|
|
</div>
|
|
<div class="collapse navbar-collapse">
|
|
<ul class="nav navbar-nav">
|
|
<li><a href="index.html">Overview</a></li>
|
|
<li><a href="api.html">API</a></li>
|
|
<li class="active"><a href="documentation.html">Documentation</a></li>
|
|
<li><a href="tutorial.html">Tutorial</a></li>
|
|
<li><a href="downloads.html">Downloads</a></li>
|
|
<li><a href="development.html">Development</a></li>
|
|
<li><a href="blog.html">Blog</a></li>
|
|
</ul>
|
|
</div>
|
|
<!--/.nav-collapse -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="container">
|
|
|
|
<div class="page-header">
|
|
<h1 class="page-title">Documentation: Reports</h1>
|
|
<p class="lead page-description">This page discusses how to create reports in Strolch</p>
|
|
</div>
|
|
|
|
<div class="content">
|
|
|
|
<p>Since Strolch has a generic model, it was rather straight forward to create a simple API for writing reports.
|
|
In Strolch a report is defined by using its own model, i.e. a Report is a <code>Resource</code> of type
|
|
<code>Report</code>.</p>
|
|
|
|
<p>A report consists of the following parts:</p>
|
|
<ul>
|
|
<li>policy definition, thus allowing extensions</li>
|
|
<li>basic configuration like base object type, order direction, etc.</li>
|
|
<li>column definitions</li>
|
|
<li>joins</li>
|
|
<li>ordering definition</li>
|
|
<li>filters</li>
|
|
</ul>
|
|
|
|
<p>An example of a report is as follows:</p>
|
|
<pre>
|
|
<Resource Id="stockReport" Name="Stock Report" Type="Report">
|
|
|
|
<ParameterBag Id="parameters" Name="parameters" Type="Parameters">
|
|
<Parameter Id="objectType" Name="Object Type" Type="String" Interpretation="Resource-Ref" Uom="Player" Value="Player"/>
|
|
<Parameter Id="descending" Name="Descending order" Type="Boolean" Value="true"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="ordering" Name="Ordering" Type="Ordering">
|
|
<Parameter Id="name" Name="Name" Type="String" Interpretation="Resource-Ref" Uom="Player" Value="$name"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="noTeamFilter" Name="Filter" Type="Filter">
|
|
<Parameter Id="policy" Name="Filter Policy" Type="String" Interpretation="ReportFilterPolicy" Uom="key:Equals" Value="!"/>
|
|
<Parameter Id="fieldRef" Name="Field reference" Type="String" Interpretation="Resource-Ref" Uom="Slot" Value="Bags/relations/team"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="columns" Name="Display Columns" Type="Display">
|
|
<Parameter Id="name" Name="Player" Type="String" Interpretation="Resource-Ref" Uom="Player" Value="$name"/>
|
|
<Parameter Id="birthDate" Name="Birth date" Type="String" Interpretation="Resource-Ref" Uom="Player" Value="Bags/parameters/birthDate"/>
|
|
<Parameter Id="team" Name="Team" Type="String" Interpretation="Resource-Ref" Uom="Team" Value="$name"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="joins" Name="Joins" Type="Joins">
|
|
<Parameter Id="Team" Name="Team" Type="String" Interpretation="Resource-Ref" Uom="Team" Value="Player"/>
|
|
</ParameterBag>
|
|
|
|
<Policies>
|
|
<Policy Type="ReportPolicy" Value="java:li.strolch.report.policy.GenericReport"/>
|
|
</Policies>
|
|
|
|
</Resource></pre>
|
|
|
|
<p>This report</p>
|
|
<ul>
|
|
<li>shows all Resources of type player (parameter <code>objectType</code>)</li>
|
|
<li>orders the report by player's name (parameter bag <code>ordering</code>)</li>
|
|
<li>filters out all players with no team assigned (parameter bag <code>noTeamFilter</code>)</li>
|
|
<li>defines three columns: Player, Birth date, Team (paramger bag <code>columns</code>)</li>
|
|
<li>joins in the resource of type <code>Team</code></li>
|
|
<li>Uses the <code>GenericReport</code> class to generate the report</li>
|
|
</ul>
|
|
|
|
<h2>GenericReport</h2>
|
|
|
|
The default generic report implemented in Strolch has the following features and options:
|
|
|
|
<h3>Parameters</h3>
|
|
<p>The parameters bag can contain the following parameters:</p>
|
|
<ul>
|
|
<li><code>objectType</code> → the base type of object to get the input for the report. This means that
|
|
the <code>Interpretation</code> is set to one of:
|
|
<ul>
|
|
<li>Resource-Ref</li>
|
|
<li>Order-Ref</li>
|
|
<li>Activity-Ref</li>
|
|
</ul>
|
|
and that the <code>UOM</code> and <code>value</code> of the parameter is set to
|
|
the type of element with which to retrieve the elements from the strolch model
|
|
</li>
|
|
<li><code>descending</code> → boolean flag to define if sorting is in descending order</li>
|
|
<li><code>hideObjectTypeFromFilterCriteria</code> → flag to hide the base object type from the filter
|
|
criteria
|
|
</li>
|
|
<li><code>allowMissingColumns</code> → flag to define if no exception should be thrown if a column is
|
|
missing
|
|
</li>
|
|
<li><code>dateRangeSel</code> → defines a lookup parameter to use as a date range selector. This
|
|
requires input when executing the report
|
|
</li>
|
|
</ul>
|
|
|
|
<h3>Lookups</h3>
|
|
<p>Many of the features of the generic report rely on looking up a value on the referenced element. The
|
|
following shows the ways that a lookup can be performed:</p>
|
|
<ul>
|
|
<li><code>$id</code> → lookup the ID of the element</li>
|
|
<li><code>$name</code> → lookup the name of the element</li>
|
|
<li><code>$type</code> → lookup the type of the element</li>
|
|
<li><code>$date</code> → lookup the date of the element (only possible on <code>Order</code> and <code>Activity</code>
|
|
elements)
|
|
</li>
|
|
<li><code>$state</code> → lookup the state of the element (only possible on <code>Order</code> and
|
|
<code>Activity</code> elements)
|
|
</li>
|
|
<li><code>Bags/<bag_id>/<param_id></code> →</li>
|
|
<li><code>$search:<parent_ref_id>:Bags/<bag_id>/<param_id></code> → searches for a
|
|
parameter with the given
|
|
bag and parameter, and
|
|
if it does not exist,
|
|
looks for the parent
|
|
with the given <code>parent_ref_id</code>
|
|
on the element. This
|
|
allows a recursive
|
|
search up a tree of
|
|
elements which all have
|
|
the same parameter
|
|
referencing a parent.
|
|
<code>relations</code> bag
|
|
</li>
|
|
</ul>
|
|
|
|
<p><b>Note:</b> these definitions are set as the value of a Parameter, and the <code>Interpretation</code> and
|
|
<code>UOM</code> of the parameter is used to find the element on which to perform the lookup. I.e. the
|
|
following definition:</p>
|
|
<pre><Parameter Id="name" Name="Player" Type="String" Interpretation="Resource-Ref" Uom="Player" Value="$name"/></pre>
|
|
<p>defines that we want to lookup the name of the resource of type Player.</p>
|
|
|
|
<h3>Ordering</h3>
|
|
<p>Ordering, i.e sorting is done by adding the parameter bag with the id <code>ordering</code> and each
|
|
parameter defines a column to order by. The sequence of the ordering is defined by the index value assigned
|
|
to each parameter.</p>
|
|
|
|
<h3>Filtering</h3>
|
|
<p>Filtering use additional Strolch Policies which implement the operator function. I.e. performing an equals,
|
|
etc. The following <code>ReportFilterPolicy</code> are available and should be added in your <code>StrolchPolicies.xml</code>
|
|
file:</p>
|
|
<pre>
|
|
<StrolchPolicies>
|
|
...
|
|
<PolicyType Type="ReportFilterPolicy" Api="li.strolch.report.policy.ReportFilterPolicy">
|
|
<Policy Key="GreaterThan" Class="li.strolch.report.policy.GreaterThanReportFilter" />
|
|
<Policy Key="LessThan" Class="li.strolch.report.policy.LessThanReportFilter" />
|
|
<Policy Key="Equals" Class="li.strolch.report.policy.EqualsReportFilter" />
|
|
</PolicyType>
|
|
...
|
|
<StrolchPolicies></pre>
|
|
|
|
<p>From this we can see that we can perform a <code>GreaterThan</code>, <code>LessThan</code> and
|
|
<code>Equals</code> filtering. These filters can also be negated by prefixing the filter value with an
|
|
exclamation mark (!).</p>
|
|
|
|
<p>A special case for the filter values are filters on dates. If you are filtering on a date, then you can use
|
|
the special operator <code>now()</code>. This filter will use the current date and time and will add/subtract
|
|
the ISO8601 period passed as an argument to the operator.</p>
|
|
|
|
<p>The following shows examples of these filters:</p>
|
|
<pre>
|
|
<ParameterBag Id="minQtyFilter" Name="Filter" Type="Filter">
|
|
<Parameter Id="policy" Name="Filter Policy" Type="String" Interpretation="ReportFilterPolicy" Uom="key:GreaterThan" Value="10"/>
|
|
<Parameter Id="fieldRef" Name="Field reference" Type="String" Interpretation="Resource-Ref" Uom="Product" Value="Bags/parameters/quantity"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="notEmptyFilter" Name="Filter" Type="Filter">
|
|
<Parameter Id="policy" Name="Filter Policy" Type="String" Interpretation="ReportFilterPolicy" Uom="key:Equals" Value="!"/>
|
|
<Parameter Id="fieldRef" Name="Field reference" Type="String" Interpretation="Resource-Ref" Uom="Team" Value="Bags/relations/team"/>
|
|
</ParameterBag>
|
|
|
|
<ParameterBag Id="threeMonthsAgoFilter" Name="Filter" Type="Filter">
|
|
<Parameter Id="policy" Name="Filter Policy" Type="String" Interpretation="ReportFilterPolicy" Uom="key:LessThan" Value="now(-P3M)"/>
|
|
<Parameter Id="fieldRef" Name="Field reference" Type="String" Interpretation="Resource-Ref" Uom="FromStock" Value="$date"/>
|
|
</ParameterBag></pre>
|
|
|
|
<p><b>Note: </b> One parameter defines which policy gets used and the <code>key:<name></code> value
|
|
references a policy defined in the <code>StrolchPolicies.xml</code> file. Further the lookup is
|
|
defined in the <code>fieldRef</code> parameter.</p>
|
|
|
|
<h3>Joins</h3>
|
|
<p>To add columns from data which is not on the element denoted by the base object type, we can join further
|
|
elements. This is done by adding the parameter bag <code>joins</code> and then each parameter references an
|
|
element to join. The joining is done as follows:</p>
|
|
<ul>
|
|
<li>The <code>Intepretation</code> and <code>UOM</code> define which object we want to join, i.e. resource
|
|
of type foo
|
|
</li>
|
|
<li>The value of the parameter defines the type of element on which to find the reference</li>
|
|
<li>The join ordering is not relevant, as the tree is traversed accordingly</li>
|
|
<li>At least one join must reference the base object type</li>
|
|
<li>The lookup of the join is done by finding a parameter with any ID, which has the same <code>Interpretation</code>
|
|
and <code>UOM</code> as the join definition
|
|
</li>
|
|
</ul>
|
|
|
|
<p>Thus the following:</p>
|
|
|
|
<pre>
|
|
<ParameterBag Id="joins" Name="Joins" Type="Joins">
|
|
<Parameter Id="Team" Name="Team" Type="String" Interpretation="Resource-Ref" Uom="Team" Value="Player"/>
|
|
<Parameter Id="Country" Name="Team" Type="String" Interpretation="Resource-Ref" Uom="Country" Value="Team"/>
|
|
</ParameterBag></pre>
|
|
|
|
<p>Performs two joins: First we join a resource of type <code>Team</code> by finding the relevant parameter on
|
|
the <code>Player</code> resource, and then we lookup a resource of type <code>Country</code> on the
|
|
previously joined <code>Team</code> resource.</p>
|
|
|
|
|
|
<h3>Execution of Reports</h3>
|
|
<p>To execute a reports, we must instantiate the Report and can then directly generate a JsonObject stream,
|
|
which we can then pipe to a browser, file, etc.:</p>
|
|
<pre>
|
|
Stream<JsonObject> jsonObjectStream = new Report(tx, reportId).doReportAsJson();</pre>
|
|
|
|
<p>If you prefer a CSV report:</p>
|
|
<pre>
|
|
try (CSVPrinter csvP = new CSVPrinter(new OutputStreamWriter(out),
|
|
CSVFormat.DEFAULT.withHeader(headers).withDelimiter(';'))) {
|
|
|
|
// do report without AsJson, and then iterating each row and sending to a CSV writer
|
|
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);
|
|
}
|
|
});
|
|
}
|
|
</pre>
|
|
|
|
<h3>Filter Criteria</h3>
|
|
<p>Predefining filters is a good start, but in some case you only want a portion of the actual filtered data.
|
|
For instance if you make a stock report, you might only want one location. This information is dynamic and
|
|
thus not stored on the report definition.</p>
|
|
|
|
<p>To perform these dynamic filterings, one would call the <code>filter()</code> method on the report, passing
|
|
the type of element to be filtered, and to which element IDs to reduce the report data to. The following
|
|
reduces the report to only return the rows with the <code>product01</code> Product and
|
|
<code>location02</code> Location elements:</p>
|
|
<pre>
|
|
new Report(tx, "stockReport")
|
|
.filter("Product", "product01")
|
|
.filter("Location", "location02")
|
|
.doReportAsJson()</pre>
|
|
|
|
<p>It is possible to find the possible filter criteria dynamically using the
|
|
<code>generateFilterCriteria()</code> method.</p>
|
|
|
|
|
|
<h3>Date Range Filtering</h3>
|
|
|
|
<p>The last option to filter dynamically is using a date range selector. Define the <code>dateRangeSel</code>
|
|
lookup parameter, and then set the date range on the instantiated report:</p>
|
|
<pre>
|
|
<ParameterBag Id="parameters" Name="parameters" Type="Parameters">
|
|
...
|
|
<Parameter Id="dateRangeSel" Name="Date Range Selector" Type="String" Interpretation="Resource-Ref" Uom="Product" Value="Bags/parameters/expirationDate"/>
|
|
...
|
|
</ParameterBag>
|
|
|
|
Date from = new Date(LocalDate.of(2016, 1, 1).toEpochDay() * 86400000);
|
|
Date to = new Date(LocalDate.of(2017, 1, 1).toEpochDay() * 86400000);
|
|
DateRange dateRange = new DateRange().from(from, true).to(to, false);
|
|
List<JsonObject> result = new Report(tx, "stockReport") //
|
|
.filter("Product", "product01") //
|
|
.dateRange(dateRange) //
|
|
.doReportAsJson()
|
|
</pre>
|
|
|
|
<p><b>Note:</b> See the
|
|
<a href="https://github.com/4treesCH/strolch/blob/develop/li.strolch.service/src/test/java/li/strolch/report/GenericReportTest.java"
|
|
target="_blank">GenericReportTest</a> for examples.</p>
|
|
|
|
|
|
<!-- content here -->
|
|
|
|
</div>
|
|
<!-- /.content -->
|
|
|
|
<div id="footer">
|
|
<div class="container">
|
|
<p class="text-muted">© Strolch / <a href="mailto:eitch@eitchnet.ch">Robert von Burg</a> / Hosting by
|
|
<a href="http://www.eitchnet.ch">eitchnet.ch</a></p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<!-- /.container -->
|
|
|
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
|
|
<!-- Include all compiled plugins (below), or include individual xsd as needed -->
|
|
<script src="js/bootstrap.min.js"></script>
|
|
|
|
<!-- Piwik -->
|
|
<script type="text/javascript">
|
|
var _paq = _paq || [];
|
|
_paq.push(['trackPageView']);
|
|
_paq.push(['enableLinkTracking']);
|
|
(function () {
|
|
var u = (("https:" == document.location.protocol) ? "https" : "http") + "://piwik.eitchnet.ch/";
|
|
_paq.push(['setTrackerUrl', u + 'piwik.php']);
|
|
_paq.push(['setSiteId', 2]);
|
|
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
|
|
g.type = 'text/javascript';
|
|
g.defer = true;
|
|
g.async = true;
|
|
g.src = u + 'piwik.js';
|
|
s.parentNode.insertBefore(g, s);
|
|
})();
|
|
</script>
|
|
<noscript><p><img src="http://piwik.eitchnet.ch/piwik.php?idsite=2" style="border:0;" alt="" /></p></noscript>
|
|
<!-- End Piwik Code -->
|
|
|
|
</body>
|
|
</html>
|