dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #37384
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 19136: Event analytics, data item prefix for option when data items are collapsed. Introduced enum Value...
Merge authors:
Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 19136 [merge]
committer: Lars Helge Overland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2015-05-11 22:15:52 +0200
message:
Event analytics, data item prefix for option when data items are collapsed. Introduced enum ValueType. Using integer as well as double as event analytics column types depending on data element/attribute value type.
added:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/ValueType.java
modified:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java
dhis-2/dhis-api/src/main/java/org/hisp/dhis/legend/LegendSet.java
dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java
dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java
dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java
--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk
Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java 2015-03-03 16:54:51 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/QueryItem.java 2015-05-11 11:58:34 +0000
@@ -120,6 +120,11 @@
return legendSet != null;
}
+ public boolean hasOptionSet()
+ {
+ return optionSet != null;
+ }
+
public String getLegendSetUid()
{
return legendSet != null ? legendSet.getUid() : null;
=== added file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/ValueType.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/ValueType.java 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/ValueType.java 2015-05-11 14:01:03 +0000
@@ -0,0 +1,160 @@
+package org.hisp.dhis.common;
+
+/*
+ * Copyright (c) 2004-2015, University of Oslo
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * Neither the name of the HISP project nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+import java.util.Date;
+
+import org.hisp.dhis.dataelement.DataElement;
+import org.hisp.dhis.trackedentity.TrackedEntityAttribute;
+
+/**
+ * @author Lars Helge Overland
+ */
+public enum ValueType
+{
+ TEXT( String.class ),
+ LONG_TEXT( String.class ),
+ LETTER( String.class ),
+ TYPE_PHONE_NUMBER( String.class ),
+ EMAIL( String.class ),
+ BOOLEAN( Boolean.class ),
+ TRUE_ONLY( Boolean.class ),
+ DATE( Date.class ),
+ NUMBER( Double.class ),
+ UNIT_INTERVAL( Double.class ),
+ PERCENTAGE( Double.class ),
+ INTEGER( Integer.class ),
+ INTEGER_POSITIVE( Integer.class ),
+ INTEGER_NEGATIVE( Integer.class ),
+ INTEGER_ZERO_OR_POSITIVE( Integer.class ),
+ NEGATIVE_INTEGER( Integer.class );
+
+ private final Class<?> javaClass;
+
+ private ValueType()
+ {
+ this.javaClass = null;
+ }
+
+ private ValueType( Class<?> javaClass )
+ {
+ this.javaClass = javaClass;
+ }
+
+ public Class<?> getJavaClass()
+ {
+ return javaClass;
+ }
+
+ /**
+ * TODO replace string value type on data element with ValueType and remove
+ * this method.
+ */
+ public static ValueType getFromDataElement( DataElement dataElement )
+ {
+ if ( DataElement.VALUE_TYPE_STRING.equals( dataElement.getType() ) )
+ {
+ if ( DataElement.VALUE_TYPE_LONG_TEXT.equals( dataElement.getTextType() ) )
+ {
+ return ValueType.LONG_TEXT;
+ }
+ else
+ {
+ return ValueType.TEXT;
+ }
+ }
+ else if ( DataElement.VALUE_TYPE_INT.equals( dataElement.getType() ) )
+ {
+ if ( DataElement.VALUE_TYPE_UNIT_INTERVAL.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.UNIT_INTERVAL;
+ }
+ else if ( DataElement.VALUE_TYPE_PERCENTAGE.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.PERCENTAGE;
+ }
+ else if ( DataElement.VALUE_TYPE_INT.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.INTEGER;
+ }
+ else if ( DataElement.VALUE_TYPE_POSITIVE_INT.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.INTEGER_POSITIVE;
+ }
+ else if ( DataElement.VALUE_TYPE_ZERO_OR_POSITIVE_INT.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.INTEGER_ZERO_OR_POSITIVE;
+ }
+ else if ( DataElement.VALUE_TYPE_NEGATIVE_INT.equals( dataElement.getNumberType() ) )
+ {
+ return ValueType.INTEGER_NEGATIVE;
+ }
+ else
+ {
+ return ValueType.NUMBER;
+ }
+ }
+ else if ( DataElement.VALUE_TYPE_BOOL.equals( dataElement.getType() ) )
+ {
+ return ValueType.BOOLEAN;
+ }
+ else if ( DataElement.VALUE_TYPE_TRUE_ONLY.equals( dataElement.getType() ) )
+ {
+ return ValueType.TRUE_ONLY;
+ }
+ else if ( DataElement.VALUE_TYPE_DATE.equals( dataElement.getType() ) )
+ {
+ return ValueType.DATE;
+ }
+
+ return ValueType.TEXT; // Fall back
+ }
+
+ /**
+ * TODO replace string value type on attribute with ValueType and remove
+ * this method.
+ */
+ public static ValueType getFromAttribute( TrackedEntityAttribute attribute )
+ {
+ if ( TrackedEntityAttribute.TYPE_NUMBER.equals( attribute.getValueType() ) )
+ {
+ return ValueType.NUMBER;
+ }
+ else if ( TrackedEntityAttribute.TYPE_BOOL.equals( attribute.getValueType() ) || TrackedEntityAttribute.TYPE_TRUE_ONLY.equals( attribute.getValueType() ) )
+ {
+ return ValueType.BOOLEAN;
+ }
+ else if ( TrackedEntityAttribute.TYPE_DATE.equals( attribute.getValueType() ) )
+ {
+ return ValueType.DATE;
+ }
+
+ return ValueType.TEXT; // Fall back
+ }
+}
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/legend/LegendSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/legend/LegendSet.java 2015-02-26 15:21:29 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/legend/LegendSet.java 2015-05-11 14:01:03 +0000
@@ -78,6 +78,19 @@
{
legends.clear();
}
+
+ public Legend getLegendByUid( String uid )
+ {
+ for ( Legend legend : legends )
+ {
+ if ( legend != null && legend.getUid().equals( uid ) )
+ {
+ return legend;
+ }
+ }
+
+ return null;
+ }
// -------------------------------------------------------------------------
// Getters and setters
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java 2015-04-20 16:36:41 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/option/OptionSet.java 2015-05-11 14:01:03 +0000
@@ -111,6 +111,19 @@
return codes;
}
+ public Option getOptionByCode( String code )
+ {
+ for ( Option option : options )
+ {
+ if ( option != null && option.getCode().equals( code ) )
+ {
+ return option;
+ }
+ }
+
+ return null;
+ }
+
// -------------------------------------------------------------------------
// Getters and setters
// -------------------------------------------------------------------------
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java 2015-04-17 12:41:18 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/trackedentity/TrackedEntityAttribute.java 2015-05-11 11:58:34 +0000
@@ -56,17 +56,17 @@
public class TrackedEntityAttribute
extends BaseDimensionalObject
{
- public static final String TYPE_DATE = "date";
public static final String TYPE_STRING = "string";
+ public static final String TYPE_PHONE_NUMBER = "phoneNumber";
+ public static final String TYPE_EMAIL = "email";
public static final String TYPE_NUMBER = "number";
public static final String TYPE_LETTER = "letter";
public static final String TYPE_BOOL = "bool";
public static final String TYPE_TRUE_ONLY = "trueOnly";
+ public static final String TYPE_DATE = "date";
public static final String TYPE_OPTION_SET = "optionSet";
- public static final String TYPE_PHONE_NUMBER = "phoneNumber";
public static final String TYPE_TRACKER_ASSOCIATE = "trackerAssociate";
public static final String TYPE_USERS = "users";
- public static final String TYPE_EMAIL = "email";
private String description;
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java 2015-03-24 11:45:27 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/EventQueryParams.java 2015-05-11 11:58:34 +0000
@@ -46,6 +46,7 @@
import org.hisp.dhis.common.NameableObjectUtils;
import org.hisp.dhis.common.QueryItem;
import org.hisp.dhis.legend.Legend;
+import org.hisp.dhis.option.OptionSet;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.period.Period;
import org.hisp.dhis.program.Program;
@@ -229,6 +230,24 @@
return legends;
}
+ /**
+ * Get option sets part of items.
+ */
+ public Set<OptionSet> getItemOptionSets()
+ {
+ Set<OptionSet> optionSets = new HashSet<>();
+
+ for ( QueryItem item : items )
+ {
+ if ( item.hasOptionSet() )
+ {
+ optionSets.add( item.getOptionSet() );
+ }
+ }
+
+ return optionSets;
+ }
+
public boolean isOrganisationUnitMode( String mode )
{
return organisationUnitMode != null && organisationUnitMode.equalsIgnoreCase( mode );
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-04-09 09:02:42 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/DefaultEventAnalyticsService.java 2015-05-11 11:58:34 +0000
@@ -191,8 +191,10 @@
{
for ( QueryItem item : params.getItems() )
{
+ //TODO use ValueType for type
+
String legendSet = item.hasLegendSet() ? item.getLegendSet().getUid() : null;
-
+
grid.addHeader( new GridHeader( item.getItem().getUid(), item.getItem().getName(), item.getTypeAsString(), false, true, item.getOptionSetUid(), legendSet ) );
}
}
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java 2015-02-25 15:59:31 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/event/data/JdbcEventAnalyticsManager.java 2015-05-11 14:01:03 +0000
@@ -59,6 +59,8 @@
import org.hisp.dhis.common.QueryFilter;
import org.hisp.dhis.common.QueryItem;
import org.hisp.dhis.jdbc.StatementBuilder;
+import org.hisp.dhis.legend.Legend;
+import org.hisp.dhis.option.Option;
import org.hisp.dhis.organisationunit.OrganisationUnit;
import org.hisp.dhis.system.util.MathUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -77,6 +79,8 @@
private static final Log log = LogFactory.getLog( JdbcEventAnalyticsManager.class );
private static final String QUERY_ERR_MSG = "Query failed, likely because the requested analytics table does not exist";
+ private static final String ITEM_NAME_SEP = ": ";
+ private static final String NA = "[N/A]";
@Autowired
private JdbcTemplate jdbcTemplate;
@@ -170,8 +174,9 @@
for ( QueryItem queryItem : params.getItems() )
{
- String itemValue = rowSet.getString( queryItem.getItemName() );
- grid.addValue( itemValue );
+ String itemValue = rowSet.getString( queryItem.getItemName() );
+ String gridValue = params.isCollapseDataDimensions() ? getCollapsedDataItemValue( params, queryItem, itemValue ) : itemValue;
+ grid.addValue( gridValue );
}
if ( params.hasValueDimension() )
@@ -552,4 +557,36 @@
return StringUtils.defaultIfEmpty( fixedCols + ", ", fixedCols );
}
+
+ /**
+ * Returns an item value for the given query, query item and value. Assumes that
+ * data dimensions are collapsed for the given query. Returns the short name
+ * of the given query item followed by the item value. If the given query item
+ * has a legend set, the item value is treated as an id and substituted with
+ * the matching legend name. If the given query item has an option set, the
+ * item value is treated as a code and substituted with the matching option
+ * name.
+ */
+ private String getCollapsedDataItemValue( EventQueryParams params, QueryItem item, String itemValue )
+ {
+ String value = item.getItem().getDisplayShortName() + ITEM_NAME_SEP;
+
+ Legend legend = null;
+ Option option = null;
+
+ if ( item.hasLegendSet() && ( legend = item.getLegendSet().getLegendByUid( itemValue ) ) != null )
+ {
+ return value + legend.getDisplayName();
+ }
+ else if ( item.hasOptionSet() && ( option = item.getOptionSet().getOptionByCode( itemValue ) ) != null )
+ {
+ return value + option.getDisplayName();
+ }
+ else
+ {
+ itemValue = StringUtils.defaultString( itemValue, NA );
+
+ return value + itemValue;
+ }
+ }
}
=== modified file 'dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java'
--- dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java 2015-03-13 15:48:26 +0000
+++ dhis-2/dhis-services/dhis-service-analytics/src/main/java/org/hisp/dhis/analytics/table/JdbcEventAnalyticsTableManager.java 2015-05-11 11:58:34 +0000
@@ -40,6 +40,7 @@
import java.util.concurrent.Future;
import org.hisp.dhis.analytics.AnalyticsTable;
+import org.hisp.dhis.common.ValueType;
import org.hisp.dhis.dataelement.DataElement;
import org.hisp.dhis.organisationunit.OrganisationUnitGroupSet;
import org.hisp.dhis.organisationunit.OrganisationUnitLevel;
@@ -224,10 +225,8 @@
public List<String[]> getDimensionColumns( AnalyticsTable table )
{
final String dbl = statementBuilder.getDoubleColumnType();
- final String text = "character varying(255)";
final String numericClause = " and value " + statementBuilder.getRegexpMatch() + " '"
+ MathUtils.NUMERIC_LENIENT_REGEXP + "'";
- final String doubleSelect = "cast(value as " + dbl + ")";
List<String[]> columns = new ArrayList<>();
@@ -261,9 +260,10 @@
for ( DataElement dataElement : table.getProgram().getAllDataElements() )
{
- String dataType = dataElement.isNumericType() ? dbl : text;
+ ValueType valueType = ValueType.getFromDataElement( dataElement );
+ String dataType = getColumnType( valueType );
String dataClause = dataElement.isNumericType() ? numericClause : "";
- String select = dataElement.isNumericType() ? doubleSelect : "value";
+ String select = getSelectClause( valueType );
String sql = "(select " + select + " from trackedentitydatavalue where programstageinstanceid=psi.programstageinstanceid " +
"and dataelementid=" + dataElement.getId() + dataClause + ") as " + quote( dataElement.getUid() );
@@ -275,9 +275,10 @@
for ( DataElement dataElement : table.getProgram().getDataElementsWithLegendSet() )
{
String column = quote( dataElement.getUid() + PartitionUtils.SEP + dataElement.getLegendSet().getUid() );
+ String select = getSelectClause( ValueType.getFromDataElement( dataElement ) );
String sql = "(select l.uid from maplegend l inner join maplegendsetmaplegend lsl on l.maplegendid=lsl.maplegendid " +
- "inner join trackedentitydatavalue dv on l.startvalue <= " + doubleSelect + " and l.endvalue > " + doubleSelect + " " +
+ "inner join trackedentitydatavalue dv on l.startvalue <= " + select + " and l.endvalue > " + select + " " +
"and lsl.legendsetid=" + dataElement.getLegendSet().getId() + " and dv.programstageinstanceid=psi.programstageinstanceid " +
"and dv.dataelementid=" + dataElement.getId() + numericClause + ") as " + column;
@@ -287,9 +288,10 @@
for ( TrackedEntityAttribute attribute : table.getProgram().getTrackedEntityAttributes() )
{
- String dataType = attribute.isNumericType() ? dbl : text;
+ ValueType valueType = ValueType.getFromAttribute( attribute );
+ String dataType = getColumnType( valueType );
String dataClause = attribute.isNumericType() ? numericClause : "";
- String select = attribute.isNumericType() ? doubleSelect : "value";
+ String select = getSelectClause( valueType );
String sql = "(select " + select + " from trackedentityattributevalue where trackedentityinstanceid=pi.trackedentityinstanceid " +
"and trackedentityattributeid=" + attribute.getId() + dataClause + ") as " + quote( attribute.getUid() );
@@ -301,9 +303,10 @@
for ( TrackedEntityAttribute attribute : table.getProgram().getTrackedEntityAttributesWithLegendSet() )
{
String column = quote( attribute.getUid() + PartitionUtils.SEP + attribute.getLegendSet().getUid() );
+ String select = getSelectClause( ValueType.getFromAttribute( attribute ) );
String sql = "(select l.uid from maplegend l inner join maplegendsetmaplegend lsl on l.maplegendid=lsl.maplegendid " +
- "inner join trackedentityattributevalue av on l.startvalue <= " + doubleSelect + " and l.endvalue > " + doubleSelect + " " +
+ "inner join trackedentityattributevalue av on l.startvalue <= " + select + " and l.endvalue > " + select + " " +
"and lsl.legendsetid=" + attribute.getLegendSet().getId() + " and av.trackedentityinstanceid=pi.trackedentityinstanceid " +
"and av.trackedentityattributeid=" + attribute.getId() + numericClause + ") as " + column;
@@ -379,4 +382,43 @@
{
return null; // Not needed
}
+
+ /**
+ * Returns the database column type based on the given value type.
+ */
+ private String getColumnType( ValueType valueType )
+ {
+ if ( Double.class.equals( valueType.getJavaClass() ) )
+ {
+ return statementBuilder.getDoubleColumnType();
+ }
+ else if ( Integer.class.equals( valueType.getJavaClass() ) )
+ {
+ return "integer";
+ }
+ else
+ {
+ return "character varying(255)";
+ }
+ }
+
+ /**
+ * Returns the select clause, potentially with a cast statement, based on the
+ * given value type.
+ */
+ private String getSelectClause( ValueType valueType )
+ {
+ if ( Double.class.equals( valueType.getJavaClass() ) )
+ {
+ return "cast(value as " + statementBuilder.getDoubleColumnType() + ")";
+ }
+ else if ( Integer.class.equals( valueType.getJavaClass() ) )
+ {
+ return "cast(value as integer)";
+ }
+ else
+ {
+ return "value";
+ }
+ }
}