dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #28693
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 14350: Web API code for organisationUnit find by location coordinate.
------------------------------------------------------------
revno: 14350
committer: James Chang <jamesbchang@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2014-03-24 13:22:32 +0900
message:
Web API code for organisationUnit find by location coordinate.
modified:
dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java
dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/DefaultOrganisationUnitService.java
dhis-2/dhis-support/dhis-support-system/pom.xml
dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/GeoUtils.java
dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/organisationunit/OrganisationUnitController.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/organisationunit/OrganisationUnitService.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java 2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/organisationunit/OrganisationUnitService.java 2014-03-24 04:22:32 +0000
@@ -391,6 +391,21 @@
* @return collection of objects.
*/
Collection<OrganisationUnit> getWithinCoordinateArea( double longitude, double latitude, double distance );
+
+ /**
+ * Retrieves the parent orgunit(s) by location.
+ *
+ * @param longitude The longitude of the location.
+ * @param latitude The latitude of the location.
+ * @param topOrgUnitUid Optional. Uid of the search top level org unit (ex.
+ * Country level orgunit)
+ * @param targetLevel Optional. The level being searched.
+ *
+ * @return collection of objects.
+ */
+ Collection<OrganisationUnit> getOrgUnitByLocation( double longitude, double latitude, String topOrgUnitUid,
+ Integer targetLevel );
+
boolean isInUserHierarchy( OrganisationUnit organisationUnit );
=== 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 2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/organisationunit/DefaultOrganisationUnitService.java 2014-03-24 04:22:32 +0000
@@ -861,6 +861,158 @@
return objects;
}
+ private Collection<OrganisationUnit> getOrganisationUnitByLocation( Collection<OrganisationUnit> orgUnits_source,
+ double longitude, double latitude )
+ {
+ Collection<OrganisationUnit> orgUnits = new ArrayList<OrganisationUnit>();
+
+ for ( OrganisationUnit ou : orgUnits_source )
+ {
+ String ou_featureType = ou.getFeatureType();
+ String ou_coordinate = ou.getCoordinates();
+
+ if ( ou_featureType != null
+ && ou_coordinate != null
+ && !ou_coordinate.isEmpty()
+ && (ou_featureType.compareTo( OrganisationUnit.FEATURETYPE_POLYGON ) == 0 || ou_featureType
+ .compareTo( OrganisationUnit.FEATURETYPE_MULTIPOLYGON ) == 0) )
+ {
+
+ if ( GeoUtils.checkPointWithMultiPolygon( longitude, latitude, ou.getCoordinates(), ou_featureType ) )
+ {
+ orgUnits.add( ou );
+ System.out.println( "Location Match OU: [" + ou.getLevel() + "], " + ou.getName() + ", "
+ + ou.getUid() );
+ }
+
+ }
+ }
+
+ return orgUnits;
+
+ }
+
+ private Collection<OrganisationUnit> getTopLevelOrgUnitWithPoint( double longitude, double latitude, int searchLvl,
+ int stopLvl )
+ {
+ Collection<OrganisationUnit> orgUnits = new ArrayList<OrganisationUnit>();
+
+ // Search down the level until it finds a orgunit with
+ // polygon/multipolygon that contains the point
+
+ for ( int i = searchLvl; i <= stopLvl; i++ )
+ {
+ Collection<OrganisationUnit> orgUnits_onLevel = getOrganisationUnitByLocation(
+ getOrganisationUnitsAtLevel( i ), longitude, latitude );
+
+ if ( orgUnits_onLevel.size() > 0 )
+ {
+ orgUnits = orgUnits_onLevel;
+ break;
+ }
+ }
+
+ return orgUnits;
+ }
+
+ public Collection<OrganisationUnit> getOrgUnitByLocation( double longitude, double latitude, String topOrgUnitUid,
+ Integer targetLevel )
+ {
+ Collection<OrganisationUnit> orgUnits = new ArrayList<OrganisationUnit>();
+
+ if ( GeoUtils.checkGeoJsonPointValid( longitude, latitude ) )
+ {
+
+ OrganisationUnit topOrgUnit = null;
+
+ // 1. Get top org unit of search.
+ if ( topOrgUnitUid != null && topOrgUnitUid != "" )
+ {
+ topOrgUnit = getOrganisationUnit( topOrgUnitUid );
+ }
+ else
+ {
+ // Get top orgunit that contains the coordinate - to get a top
+ // search point.
+ Collection<OrganisationUnit> orgUnits_TopLevel = getTopLevelOrgUnitWithPoint( longitude, latitude, 1,
+ getNumberOfOrganisationalLevels() - 1 );
+
+ if ( orgUnits_TopLevel.size() == 1 )
+ {
+ topOrgUnit = orgUnits_TopLevel.iterator().next();
+ }
+ else
+ {
+ System.out.print( "Multiple Top Level Org Unit found with the coordinate: " );
+
+ for ( OrganisationUnit ou : orgUnits_TopLevel )
+ {
+ System.out.print( " [" + ou.getLevel() + "] " + ou.getName() + " " + ou.getUid() + " " );
+ }
+
+ System.out.println( "" );
+ }
+
+ }
+
+ // 2. From the found top level orgunit, search children orgunits to
+ // get the lowest level orgunit that contains the coordinate
+ if ( topOrgUnit == null )
+ {
+ System.out.println( "Could not retrieve a top org Unit." );
+ }
+ else
+ {
+ Collection<OrganisationUnit> orgUnits_childrens = new ArrayList<OrganisationUnit>();
+
+ if ( targetLevel != null )
+ {
+ orgUnits_childrens = getOrganisationUnitsAtLevel( targetLevel, topOrgUnit );
+ }
+ else
+ {
+ orgUnits_childrens = getOrganisationUnitWithChildren( topOrgUnit.getId() );
+ }
+
+ Collection<OrganisationUnit> orgUnits_found = getOrganisationUnitByLocation( orgUnits_childrens,
+ longitude, latitude );
+
+ // 3. for all the org units with polygon containing the coordinate
+ // , get polygon with highest level
+
+ int bottomLvl = topOrgUnit.getLevel();
+
+ for ( OrganisationUnit ou : orgUnits_found )
+ {
+
+ if ( ou.getLevel() > bottomLvl )
+ {
+ bottomLvl = ou.getLevel();
+ }
+ }
+
+ for ( OrganisationUnit ou : orgUnits_found )
+ {
+ if ( ou.getLevel() == bottomLvl )
+ {
+ System.out.println( "Bottom Lvl OU Found: [" + ou.getLevel() + "], " + ou.getName() + ", "
+ + ou.getUid() );
+
+ orgUnits.add( ou );
+ }
+ }
+ }
+
+ }
+ else
+ {
+ System.out.println( "Could not create a valid GeoJson Point from coordinate. Longitude: " + longitude
+ + ", latitude: " + latitude );
+ }
+
+ return orgUnits;
+ }
+
// -------------------------------------------------------------------------
// Version
// -------------------------------------------------------------------------
=== modified file 'dhis-2/dhis-support/dhis-support-system/pom.xml'
--- dhis-2/dhis-support/dhis-support-system/pom.xml 2014-03-02 05:48:08 +0000
+++ dhis-2/dhis-support/dhis-support-system/pom.xml 2014-03-24 04:22:32 +0000
@@ -59,7 +59,12 @@
<groupId>org.geotools</groupId>
<artifactId>gt-referencing</artifactId>
</dependency>
-
+ <dependency>
+ <groupId>org.geotools</groupId>
+ <artifactId>gt-geojson</artifactId>
+ <version>10.4</version>
+ </dependency>
+
<!-- Other -->
<dependency>
=== modified file 'dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/GeoUtils.java'
--- dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/GeoUtils.java 2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-support/dhis-support-system/src/main/java/org/hisp/dhis/system/util/GeoUtils.java 2014-03-24 04:22:32 +0000
@@ -29,8 +29,15 @@
*/
import java.awt.geom.Point2D;
+import java.io.StringReader;
+import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.referencing.GeodeticCalculator;
+import org.hisp.dhis.organisationunit.OrganisationUnit;
+
+import com.vividsolutions.jts.geom.MultiPolygon;
+import com.vividsolutions.jts.geom.Point;
+import com.vividsolutions.jts.geom.Polygon;
/**
* @author Lars Helge Overland
@@ -93,5 +100,77 @@
calc.setDestinationGeographicPoint( to);
return calc.getOrthodromicDistance();
- }
+ }
+
+ private static Point getGeoJsonPoint( double longitude, double latitude )
+ {
+ Point point = null;
+
+ try
+ {
+ GeometryJSON gtjson = new GeometryJSON();
+
+ point = gtjson.readPoint( new StringReader( "{\"type\":\"Point\", \"coordinates\":[" + longitude + ","
+ + latitude + "]}" ) );
+ }
+ catch ( Exception ex )
+ {
+ System.out.println( "Error during GeoJson point create - " + ex.getMessage() );
+ }
+
+ return point;
+ }
+
+ public static boolean checkGeoJsonPointValid( double longitude, double latitude )
+ {
+ return getGeoJsonPoint( longitude, latitude ).isValid();
+ }
+
+ // Check if the point is within the polygon/multiPolygon
+ public static boolean checkPointWithMultiPolygon( double longitude, double latitude, String multiPolygonJson,
+ String featureType )
+ {
+ boolean contains = false;
+
+ GeometryJSON gtjson = new GeometryJSON();
+
+ // Note: Could create this point once from calling package and reuse it
+ // , but then, each calling package need to reference
+ // 'com.vividsolutions.jts.geom.Point'
+ Point point = getGeoJsonPoint( longitude, latitude );
+
+ if ( point != null && point.isValid() )
+ {
+ try
+ {
+ if ( featureType.compareTo( OrganisationUnit.FEATURETYPE_POLYGON ) == 0 )
+ {
+ Polygon polygon = gtjson.readPolygon( new StringReader( "{\"type\":\"Polygon\", \"coordinates\":"
+ + multiPolygonJson + "}" ) );
+
+ contains = polygon.contains( point );
+ }
+ else if ( featureType.compareTo( OrganisationUnit.FEATURETYPE_MULTIPOLYGON ) == 0 )
+ {
+ MultiPolygon multiPolygon = gtjson.readMultiPolygon( new StringReader(
+ "{\"type\":\"MultiPolygon\", \"coordinates\":" + multiPolygonJson + "}" ) );
+
+ contains = multiPolygon.contains( point );
+ }
+
+ }
+ catch ( Exception exception )
+ {
+ System.out.println( "Error during GeoJson MultiPolygon create - " + exception.toString() );
+ }
+
+ }
+ else
+ {
+ System.out.println( "Point coordinate is not valid. Longitude: " + longitude + ", latitude: " + latitude );
+ }
+
+ return contains;
+ }
+
}
=== 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 2014-03-18 08:10:10 +0000
+++ dhis-2/dhis-web/dhis-web-api/src/main/java/org/hisp/dhis/api/controller/organisationunit/OrganisationUnitController.java 2014-03-24 04:22:32 +0000
@@ -306,7 +306,53 @@
}
orgunit.setAttributeValues( attributeValues );
-
+
+ // Clear out all data not needed for this task
+ orgunit.removeAllDataSets();
+ orgunit.removeAllUsers();
+ orgunit.removeAllOrganisationUnitGroups();
+ }
+
+ JacksonUtils.toJson( response.getOutputStream(), entityList );
+ }
+
+ @RequestMapping( value = "/orgUnitByLocation", method = RequestMethod.GET, produces = { "*/*", "application/json" } )
+ public void getParentByLocation( @RequestParam
+ Double longitude, @RequestParam
+ Double latitude, @RequestParam
+ Map<String, String> parameters, Model model, HttpServletRequest request, HttpServletResponse response )
+ throws Exception
+ {
+
+ // 1. Get parameters
+ WebOptions options = new WebOptions( parameters );
+
+ String topOrgUnit = null;
+ Integer targetLevel = null;
+
+ topOrgUnit = options.getOptions().get( "topOrgUnit" );
+
+ if ( options.getOptions().containsKey( "targetLevel" ) )
+ {
+ try
+ {
+ targetLevel = Integer.parseInt( options.getOptions().get( "targetLevel" ) );
+ }
+ catch ( NumberFormatException ignored )
+ {
+ }
+ }
+
+ // 2. Retrieve list - lowest level orgunit(s) containing the coordinate.
+ List<OrganisationUnit> entityList = new ArrayList<OrganisationUnit>(
+ organisationUnitService.getOrgUnitByLocation( longitude, latitude, topOrgUnit, targetLevel ) );
+
+ // 3. Remove unrelated details and output in JSON format.
+ for ( OrganisationUnit orgunit : entityList )
+ {
+ Set<AttributeValue> attributeValues = orgunit.getAttributeValues();
+ attributeValues.clear();
+
// Clear out all data not needed for this task
orgunit.removeAllDataSets();
orgunit.removeAllUsers();