=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java 2013-08-23 15:56:19 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java 2013-11-01 08:11:31 +0000 @@ -381,6 +381,19 @@ Collection getOrganisationUnitsBetweenByStatusLastUpdated( boolean status, Date lastUpdated, int first, int max ); + /** + * Retrieves the objects where its coordinate is within the 4 area points. + * 4 area points are + * Index 0: Maximum latitude (north edge of box shape) + * Index 1: Maxium longitude (east edge of box shape) + * Index 2: Minimum latitude (south edge of box shape) + * Index 3: Minumum longitude (west edge of box shape) + * + * @param box the 4 area points. + * @return collection of objects. + */ + Collection getWithinCoordinateArea( double[] box ); + // ------------------------------------------------------------------------- // OrganisationUnitHierarchy // ------------------------------------------------------------------------- === modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitStore.java' --- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitStore.java 2013-08-23 15:56:19 +0000 +++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitStore.java 2013-11-01 08:11:31 +0000 @@ -161,6 +161,20 @@ */ Collection getBetweenByStatusLastUpdated( boolean status, Date lastUpdated, int first, int max ); + + /** + * Retrieves the objects where its coordinate is within the 4 area points. + * 4 area points are + * Index 0: Maximum latitude (north edge of box shape) + * Index 1: Maxium longitude (east edge of box shape) + * Index 2: Minimum latitude (south edge of box shape) + * Index 3: Minumum longitude (west edge of box shape) + * + * @param box the 4 area points. + * @return collection of objects. + */ + Collection getWithinCoordinateArea( double[] box ); + // ------------------------------------------------------------------------- // OrganisationUnitHierarchy // ------------------------------------------------------------------------- === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/DefaultOrganisationUnitService.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/DefaultOrganisationUnitService.java 2013-08-23 16:05:01 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/DefaultOrganisationUnitService.java 2013-11-01 08:11:31 +0000 @@ -798,6 +798,11 @@ return organisationUnitLevelStore.getMaxLevels(); } + public Collection getWithinCoordinateArea( double[] box ) + { + return organisationUnitStore.getWithinCoordinateArea( box ); + } + // ------------------------------------------------------------------------- // Version // ------------------------------------------------------------------------- === modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java' --- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java 2013-08-23 16:05:01 +0000 +++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/hibernate/HibernateOrganisationUnitStore.java 2013-11-01 08:11:31 +0000 @@ -267,6 +267,20 @@ return criteria.list(); } + @SuppressWarnings("unchecked") + public Collection getWithinCoordinateArea( double[] box ) + { + return getQuery( "from OrganisationUnit o" + + " where o.featureType='Point'" + + " and o.coordinates is not null" + + " and CAST( SUBSTRING(o.coordinates, 2, LOCATE(',', o.coordinates) - 2) AS big_decimal ) >= " + box[3] + + " and CAST( SUBSTRING(o.coordinates, 2, LOCATE(',', o.coordinates) - 2) AS big_decimal ) <= " + box[1] + + " and CAST( SUBSTRING(coordinates, LOCATE(',', o.coordinates) + 1, LOCATE(']', o.coordinates) - LOCATE(',', o.coordinates) - 1 ) AS big_decimal ) >= " + box[2] + + " and CAST( SUBSTRING(coordinates, LOCATE(',', o.coordinates) + 1, LOCATE(']', o.coordinates) - LOCATE(',', o.coordinates) - 1 ) AS big_decimal ) <= " + box[0] + ).list(); + } + + // ------------------------------------------------------------------------- // OrganisationUnitHierarchy // ------------------------------------------------------------------------- === modified file 'dhis-2/dhis-services/dhis-service-mapgeneration/src/main/java/org/hisp/dhis/mapgeneration/MapUtils.java' --- dhis-2/dhis-services/dhis-service-mapgeneration/src/main/java/org/hisp/dhis/mapgeneration/MapUtils.java 2013-10-28 13:17:58 +0000 +++ dhis-2/dhis-services/dhis-service-mapgeneration/src/main/java/org/hisp/dhis/mapgeneration/MapUtils.java 2013-11-01 08:11:31 +0000 @@ -30,6 +30,7 @@ import java.awt.Color; import java.awt.Graphics2D; +import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.Point2D; @@ -337,4 +338,17 @@ return box; } + + /** + * Creates the distance between two points. + */ + public static double getDistanceBetweenTwoPoints( Point2D from, Point2D to) + { + GeodeticCalculator calc = new GeodeticCalculator(); + calc.setStartingGeographicPoint( from ); + calc.setDestinationGeographicPoint( to); + + return calc.getOrthodromicDistance(); + } + } === modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ValidationUtils.java' --- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ValidationUtils.java 2013-10-07 17:58:57 +0000 +++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/ValidationUtils.java 2013-11-01 08:11:31 +0000 @@ -33,6 +33,7 @@ import org.apache.commons.validator.routines.UrlValidator; import org.hisp.dhis.dataelement.DataElement; +import java.awt.geom.Point2D; import java.util.Arrays; import java.util.List; import java.util.Locale; @@ -198,6 +199,29 @@ return matcher.find() ? matcher.group( 2 ) : null; } + + /** + * Returns the longitude and latitude from the given coordinate. + * + * @param coordinate the coordinate string. + * @return Point2D of the coordinate. + */ + public static Point2D getCoordinatePoint2D( String coordinate ) + { + if ( coordinate == null ) + { + return null; + } + + Matcher matcher = POINT_PATTERN.matcher( coordinate ); + + if( matcher.find() && matcher.groupCount() == 2 ) + { + return new Point2D.Double( Double.parseDouble( matcher.group( 1 ) ), Double.parseDouble( matcher.group( 2 ) ) ); + } + else return null; + } + /** * Returns a coordinate string based on the given latitude and longitude. * The coordinate is on the form longitude / latitude. === modified file 'dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/organisationunit/OrganisationUnitController.java' --- dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/organisationunit/OrganisationUnitController.java 2013-10-30 10:44:00 +0000 +++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/organisationunit/OrganisationUnitController.java 2013-11-01 08:11:31 +0000 @@ -33,11 +33,17 @@ import org.hisp.dhis.api.controller.WebOptions; import org.hisp.dhis.api.controller.exception.NotFoundException; import org.hisp.dhis.api.utils.WebUtils; +import org.hisp.dhis.attribute.Attribute; +import org.hisp.dhis.attribute.AttributeValue; import org.hisp.dhis.common.Pager; import org.hisp.dhis.dxf2.metadata.MetaData; +import org.hisp.dhis.dxf2.utils.JacksonUtils; +import org.hisp.dhis.mapgeneration.MapUtils; import org.hisp.dhis.organisationunit.OrganisationUnit; +import org.hisp.dhis.organisationunit.OrganisationUnitGroup; import org.hisp.dhis.organisationunit.OrganisationUnitService; import org.hisp.dhis.organisationunit.comparator.OrganisationUnitByLevelComparator; +import org.hisp.dhis.system.util.ValidationUtils; import org.hisp.dhis.user.CurrentUserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @@ -50,11 +56,15 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; + +import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; /** * @author Morten Olav Hansen @@ -247,4 +257,67 @@ return StringUtils.uncapitalize( getEntitySimpleName() ); } + + + @RequestMapping(value = "/withinRange", method = RequestMethod.GET, produces = { "*/*", "application/json" }) + public void getEntitiesWithinRange( @RequestParam Map parameters, + Model model, HttpServletRequest request, HttpServletResponse response ) throws Exception + { + List entityList; + + WebOptions options = new WebOptions( parameters ); + + Double longitude = Double.parseDouble( options.getOptions().get( "longitude" ) ); + Double latitude = Double.parseDouble( options.getOptions().get( "latitude" ) ); + Double distance = Double.parseDouble( options.getOptions().get( "distance" ) ); + + entityList = new ArrayList( organisationUnitService.getWithinCoordinateArea( MapUtils.getBoxShape( longitude, latitude, distance ) ) ); + + Point2D centerPoint = new Point2D.Double( longitude, latitude ); + + if ( entityList != null ) + { + Iterator iter = entityList.iterator(); + + while ( iter.hasNext() ) + { + OrganisationUnit orgunit = iter.next(); + + double distancebetween = MapUtils.getDistanceBetweenTwoPoints( centerPoint, + ValidationUtils.getCoordinatePoint2D( orgunit.getCoordinates() ) ); + + if ( distancebetween > distance ) + { + // Remove the orgUnits that is outside of the distance range + // - due to the 'getWithinCoordinateArea' looking at square area instead of circle. + iter.remove(); + } + else + { + // Clear out all data not needed for this task + orgunit.removeAllDataSets(); + orgunit.removeAllUsers(); + orgunit.removeAllOrganisationUnitGroups(); + + Set attributeValues = orgunit.getAttributeValues(); + attributeValues.clear(); + + // Add OrgUnit Group Symbol into attributes + for ( OrganisationUnitGroup orgunitGroup : orgunit.getGroups() ) + { + AttributeValue attributeValue = new AttributeValue(); + attributeValue.setAttribute( new Attribute( "OrgUnitGroupSymbol", "OrgUnitGroupSymbol" ) ); + attributeValue.setValue( orgunitGroup.getSymbol() ); + + attributeValues.add( attributeValue ); + } + + orgunit.setAttributeValues( attributeValues ); + } + } + } + + JacksonUtils.toJson( response.getOutputStream(), entityList ); + } + }