← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18290: extended getAll/getBetween to support multiple orders, also added new OrderOptions class to enabl...

 

------------------------------------------------------------
revno: 18290
committer: Morten Olav Hansen <mortenoh@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2015-02-17 14:22:47 +0700
message:
  extended getAll/getBetween to support multiple orders, also added new OrderOptions class to enable criteria based order in AbstractCrudController, ?order=propertyName:asc/desc
added:
  dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/common/OrderOptions.java
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Order.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/Schema.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java
  dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java
  dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.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/GenericStore.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java	2015-02-17 05:01:28 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/GenericStore.java	2015-02-17 07:22:47 +0000
@@ -99,6 +99,13 @@
     List<T> getAll( Order order );
 
     /**
+     * Retrieves a List of all objects, ordered as specified (only persisted properties are supported).
+     *
+     * @return a List of all objects.
+     */
+    List<T> getAll( List<Order> order );
+
+    /**
      * Retrieves a paged List of all objects.
      *
      * @return a List of all objects.
@@ -113,6 +120,13 @@
     List<T> getAll( int first, int max, Order order );
 
     /**
+     * Retrieves a paged List of all objects, ordered as specified (only persisted properties are supported).
+     *
+     * @return a List of all objects.
+     */
+    List<T> getAll( int first, int max, List<Order> order );
+
+    /**
      * Removes the given object instance.
      *
      * @param object the object instance to delete.

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java	2015-02-17 05:01:28 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/common/IdentifiableObjectManager.java	2015-02-17 07:22:47 +0000
@@ -72,6 +72,8 @@
 
     <T extends IdentifiableObject> Collection<T> getAll( Class<T> clazz, Order order );
 
+    <T extends IdentifiableObject> Collection<T> getAll( Class<T> clazz, List<Order> order );
+
     <T extends IdentifiableObject> Collection<T> getAllByName( Class<T> clazz, String name );
 
     <T extends IdentifiableObject> Collection<T> getAllByNameIgnoreCase( Class<T> clazz, String name );
@@ -90,6 +92,8 @@
 
     <T extends IdentifiableObject> List<T> getBetween( Class<T> clazz, int first, int max, Order order );
 
+    <T extends IdentifiableObject> List<T> getBetween( Class<T> clazz, int first, int max, List<Order> order );
+
     <T extends IdentifiableObject> List<T> getBetweenSorted( Class<T> clazz, int first, int max );
 
     <T extends IdentifiableObject> List<T> getBetweenLikeName( Class<T> clazz, String name, int first, int max );

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Order.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Order.java	2015-02-17 05:01:28 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/query/Order.java	2015-02-17 07:22:47 +0000
@@ -28,8 +28,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import com.google.common.base.MoreObjects;
 import org.hisp.dhis.schema.Property;
 
+import java.util.Objects;
+
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
  */
@@ -77,4 +80,40 @@
     {
         return new Order( property, false );
     }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( ascending, ignoreCase, property );
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( obj == null || getClass() != obj.getClass() )
+        {
+            return false;
+        }
+
+        final Order other = (Order) obj;
+
+        return Objects.equals( this.ascending, other.ascending )
+            && Objects.equals( this.ignoreCase, other.ignoreCase )
+            && Objects.equals( this.property, other.property );
+    }
+
+    @Override
+    public String toString()
+    {
+        return MoreObjects.toStringHelper( this )
+            .add( "ascending", ascending )
+            .add( "ignoreCase", ignoreCase )
+            .add( "property", property != null ? property.getName() : null )
+            .toString();
+    }
 }

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/Schema.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/Schema.java	2015-01-17 07:41:26 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/schema/Schema.java	2015-02-17 07:22:47 +0000
@@ -28,14 +28,6 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-import java.util.List;
-import java.util.Map;
-
-import org.hisp.dhis.common.DxfNamespaces;
-import org.hisp.dhis.common.IdentifiableObject;
-import org.hisp.dhis.common.NameableObject;
-import org.springframework.core.Ordered;
-
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper;
@@ -45,6 +37,13 @@
 import com.google.common.base.Objects;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import org.hisp.dhis.common.DxfNamespaces;
+import org.hisp.dhis.common.IdentifiableObject;
+import org.hisp.dhis.common.NameableObject;
+import org.springframework.core.Ordered;
+
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
@@ -323,6 +322,11 @@
         return Lists.newArrayList( propertyMap.values() );
     }
 
+    public boolean haveProperty( String propertyName )
+    {
+        return getPropertyMap().containsKey( propertyName );
+    }
+
     @JsonIgnore
     public Map<String, Property> getPropertyMap()
     {

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	2015-02-17 05:01:28 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/common/DefaultIdentifiableObjectManager.java	2015-02-17 07:22:47 +0000
@@ -28,6 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import com.google.common.collect.Lists;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.SessionFactory;
@@ -267,9 +268,15 @@
     }
 
     @Override
-    @SuppressWarnings( "unchecked" )
     public <T extends IdentifiableObject> Collection<T> getAll( Class<T> clazz, Order order )
     {
+        return getAll( clazz, Lists.newArrayList( order ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T extends IdentifiableObject> Collection<T> getAll( Class<T> clazz, List<Order> order )
+    {
         GenericIdentifiableObjectStore<IdentifiableObject> store = getIdentifiableObjectStore( clazz );
 
         if ( store == null )
@@ -484,9 +491,15 @@
     }
 
     @Override
-    @SuppressWarnings( "unchecked" )
     public <T extends IdentifiableObject> List<T> getBetween( Class<T> clazz, int first, int max, Order order )
     {
+        return getBetween( clazz, first, max, Lists.newArrayList( order ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public <T extends IdentifiableObject> List<T> getBetween( Class<T> clazz, int first, int max, List<Order> order )
+    {
         GenericIdentifiableObjectStore<IdentifiableObject> store = getIdentifiableObjectStore( clazz );
 
         if ( store == null )

=== added file 'dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/common/OrderOptions.java'
--- dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/common/OrderOptions.java	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-services/dhis-service-dxf2/src/main/java/org/hisp/dhis/dxf2/common/OrderOptions.java	2015-02-17 07:22:47 +0000
@@ -0,0 +1,138 @@
+package org.hisp.dhis.dxf2.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 com.google.common.base.MoreObjects;
+import org.hisp.dhis.query.Order;
+import org.hisp.dhis.schema.Property;
+import org.hisp.dhis.schema.Schema;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * @author Morten Olav Hansen <mortenoh@xxxxxxxxx>
+ */
+public class OrderOptions
+{
+    private Set<String> order = new HashSet<>();
+
+    public OrderOptions()
+    {
+    }
+
+    public void setOrder( Set<String> order )
+    {
+        this.order = order;
+    }
+
+    public List<Order> getOrders( Schema schema )
+    {
+        Map<String, Order> orders = new HashMap<>();
+
+        for ( String o : order )
+        {
+            String[] split = o.split( ":" );
+
+            if ( split.length <= 1 )
+            {
+                continue;
+            }
+
+            if ( orders.containsKey( split[0] ) || !schema.haveProperty( split[0] )
+                || !validProperty( schema.getProperty( split[0] ) ) || !validDirection( split[1] ) )
+            {
+                continue;
+            }
+
+            Order newOrder;
+
+            if ( "asc".equals( split[1] ) )
+            {
+                newOrder = Order.asc( schema.getProperty( split[0] ) );
+            }
+            else
+            {
+                newOrder = Order.desc( schema.getProperty( split[0] ) );
+            }
+
+            orders.put( split[0], newOrder.ignoreCase() );
+        }
+
+        return new ArrayList<>( orders.values() );
+    }
+
+    private boolean validProperty( Property property )
+    {
+        return property.isPersisted() && property.isSimple();
+    }
+
+    private boolean validDirection( String direction )
+    {
+        return "asc".equals( direction ) || "desc".equals( direction );
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hash( order );
+    }
+
+    @Override
+    public boolean equals( Object obj )
+    {
+        if ( this == obj )
+        {
+            return true;
+        }
+
+        if ( obj == null || getClass() != obj.getClass() )
+        {
+            return false;
+        }
+
+        final OrderOptions other = (OrderOptions) obj;
+
+        return Objects.equals( this.order, other.order );
+    }
+
+
+    @Override
+    public String toString()
+    {
+        return MoreObjects.toStringHelper( this )
+            .add( "order", order )
+            .toString();
+    }
+}

=== modified file 'dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java'
--- dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java	2015-02-17 05:01:28 +0000
+++ dhis-2/dhis-support/dhis-support-hibernate/src/main/java/org/hisp/dhis/hibernate/HibernateGenericStore.java	2015-02-17 07:22:47 +0000
@@ -28,6 +28,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+import com.google.common.collect.Lists;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.hibernate.Criteria;
@@ -63,6 +64,7 @@
 import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -437,20 +439,24 @@
     }
 
     @Override
-    @SuppressWarnings( "unchecked" )
     public final List<T> getAll( Order order )
     {
+        return getAll( Lists.newArrayList( order ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public List<T> getAll( List<Order> order )
+    {
         Criteria criteria = getSharingCriteria();
-        org.hibernate.criterion.Order criteriaOrder = getHibernateOrder( order );
+        List<org.hibernate.criterion.Order> hibernateOrders = getHibernateOrders( order );
 
-        if ( criteriaOrder == null )
+        for ( org.hibernate.criterion.Order ho : hibernateOrders )
         {
-            return criteria.list();
+            criteria.addOrder( ho );
         }
 
-        return criteria
-            .addOrder( criteriaOrder )
-            .list();
+        return criteria.list();
     }
 
     @Override
@@ -464,19 +470,24 @@
     }
 
     @Override
-    @SuppressWarnings( "unchecked" )
     public List<T> getAll( int first, int max, Order order )
     {
+        return getAll( first, max, Lists.newArrayList( order ) );
+    }
+
+    @Override
+    @SuppressWarnings( "unchecked" )
+    public List<T> getAll( int first, int max, List<Order> order )
+    {
         Criteria criteria = getSharingCriteria();
-        org.hibernate.criterion.Order criteriaOrder = getHibernateOrder( order );
+        List<org.hibernate.criterion.Order> hibernateOrders = getHibernateOrders( order );
 
-        if ( criteriaOrder == null )
+        for ( org.hibernate.criterion.Order ho : hibernateOrders )
         {
-            return criteria.list();
+            criteria.addOrder( ho );
         }
 
         return criteria
-            .addOrder( criteriaOrder )
             .setFirstResult( first )
             .setMaxResults( max )
             .list();
@@ -590,9 +601,26 @@
         return true;
     }
 
+    protected List<org.hibernate.criterion.Order> getHibernateOrders( List<Order> order )
+    {
+        List<org.hibernate.criterion.Order> orders = new ArrayList<>();
+
+        for ( Order o : order )
+        {
+            org.hibernate.criterion.Order hibernateOrder = getHibernateOrder( o );
+
+            if ( hibernateOrder != null )
+            {
+                orders.add( hibernateOrder );
+            }
+        }
+
+        return orders;
+    }
+
     protected org.hibernate.criterion.Order getHibernateOrder( Order order )
     {
-        if ( order.getProperty() == null || !order.getProperty().isPersisted() )
+        if ( order.getProperty() == null || !order.getProperty().isPersisted() || !order.getProperty().isSimple() )
         {
             return null;
         }

=== modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java'
--- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java	2015-02-17 06:00:52 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/webapi/controller/AbstractCrudController.java	2015-02-17 07:22:47 +0000
@@ -38,11 +38,12 @@
 import org.hisp.dhis.common.IdentifiableObjectManager;
 import org.hisp.dhis.common.Pager;
 import org.hisp.dhis.common.PagerUtils;
+import org.hisp.dhis.dxf2.common.OrderOptions;
+import org.hisp.dhis.dxf2.common.TranslateOptions;
 import org.hisp.dhis.dxf2.fieldfilter.FieldFilterService;
 import org.hisp.dhis.dxf2.importsummary.ImportStatus;
 import org.hisp.dhis.dxf2.metadata.ImportService;
 import org.hisp.dhis.dxf2.metadata.ImportTypeSummary;
-import org.hisp.dhis.dxf2.common.TranslateOptions;
 import org.hisp.dhis.dxf2.objectfilter.ObjectFilterService;
 import org.hisp.dhis.dxf2.render.RenderService;
 import org.hisp.dhis.hibernate.exception.CreateAccessDeniedException;
@@ -56,6 +57,7 @@
 import org.hisp.dhis.node.types.CollectionNode;
 import org.hisp.dhis.node.types.RootNode;
 import org.hisp.dhis.node.types.SimpleNode;
+import org.hisp.dhis.query.Order;
 import org.hisp.dhis.schema.Property;
 import org.hisp.dhis.schema.Schema;
 import org.hisp.dhis.schema.SchemaService;
@@ -136,11 +138,15 @@
 
     @RequestMapping( method = RequestMethod.GET )
     public @ResponseBody RootNode getObjectList(
-        @RequestParam Map<String, String> rpParameters, TranslateOptions translateOptions, HttpServletResponse response, HttpServletRequest request )
+        @RequestParam Map<String, String> rpParameters,
+        TranslateOptions translateOptions, OrderOptions orderOptions,
+        HttpServletResponse response, HttpServletRequest request )
     {
         List<String> fields = Lists.newArrayList( contextService.getParameterValues( "fields" ) );
         List<String> filters = Lists.newArrayList( contextService.getParameterValues( "filter" ) );
 
+        List<Order> orders = orderOptions.getOrders( getSchema() );
+
         WebOptions options = new WebOptions( rpParameters );
         WebMetaData metaData = new WebMetaData();
 
@@ -155,7 +161,23 @@
 
         List<T> entities;
 
-        if ( filters.isEmpty() )
+        if ( !orders.isEmpty() )
+        {
+            if ( options.hasPaging() )
+            {
+                int count = manager.getCount( getEntityClass() );
+                Pager pager = new Pager( options.getPage(), count, options.getPageSize() );
+                metaData.setPager( pager );
+                entities = manager.getBetween( getEntityClass(), pager.getOffset(), pager.getPageSize(), orders );
+                hasPaging = false;
+            }
+            else
+            {
+                entities = (List<T>) manager.getAll( getEntityClass(), orders );
+                hasPaging = false;
+            }
+        }
+        else if ( filters.isEmpty() )
         {
             entities = getEntityList( metaData, options, filters );
             hasPaging = false;
@@ -167,7 +189,7 @@
 
             // Use database query for name filter
 
-            if ( schema.getProperty( "name" ) != null && schema.getProperty( "name" ).isPersisted() )
+            if ( schema.haveProperty( "name" ) && schema.getProperty( "name" ).isPersisted() )
             {
                 while ( iterator.hasNext() )
                 {
@@ -855,9 +877,16 @@
         return list; //TODO consider ACL
     }
 
+    private Schema schema;
+
     protected Schema getSchema()
     {
-        return schemaService.getDynamicSchema( getEntityClass() );
+        if ( schema == null )
+        {
+            schema = schemaService.getDynamicSchema( getEntityClass() );
+        }
+
+        return schema;
     }
 
     protected void addAccessProperties( List<T> objects )