Skip to content

Commit

Permalink
Merge remote-tracking branch 'grzesiek2010/JAVAROSA-318' into v2.11.1
Browse files Browse the repository at this point in the history
  • Loading branch information
lognaturel committed Jul 19, 2018
2 parents f089662 + bfd6bfc commit 65c1f02
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa" xmlns:orx="http://openrosa.org/xforms/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<h:head>
<h:title>Area with less than three points</h:title>
<model>
<instance>
<area id="area" version="2018042401">
<geoshape1>38.253094215699576 21.756382658677467;38.25021274773806 21.756382658677467</geoshape1>
<arearesult/>
<distanceresult/>
<meta>
<instanceID/>
</meta>
</area>
</instance>
<bind nodeset="/area/geoshape1" type="geoshape"/>
<bind calculate="enclosed-area( /area/geoshape1 )" nodeset="/area/arearesult" type="string"/>
<bind calculate="concat('uuid:', uuid())" nodeset="/area/meta/instanceID" readonly="true()" type="string"/>
</model>
</h:head>
<h:body>
<input ref="/area/geoshape1">
<label>Draw your shape here...</label>
</input>
</h:body>
</h:html>
5 changes: 2 additions & 3 deletions resources/org/javarosa/core/util/distance.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
<model>
<instance>
<distance id="distance" version="2018042401">
<geoshape>0 0; 0 1; 0 91</geoshape>
<geotrace>0 0; 0 1; 0 91</geotrace>
<geoshape>0 0; 0 91</geoshape>
<geotrace>0 0; 0 91</geotrace>
<points>
<point>0 0</point>
<point>0 1</point>
<point>0 91</point>
</points>
<shape-result/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<h:html xmlns="http://www.w3.org/2002/xforms" xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:h="http://www.w3.org/1999/xhtml" xmlns:jr="http://openrosa.org/javarosa"
xmlns:orx="http://openrosa.org/xforms/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<h:head>
<h:title>Distance with less than two points</h:title>
<model>
<instance>
<distance id="distance" version="2018042401">
<geotrace>0 0</geotrace>
<trace-result/>
<meta>
<instanceID/>
</meta>
</distance>
</instance>
<bind nodeset="/distance/geotrace" type="geotrace"/>
<bind calculate="distance( /distance/geotrace )" nodeset="/distance/trace-result" type="string"/>
<bind calculate="concat('uuid:', uuid())" nodeset="/distance/meta/instanceID" readonly="true()" type="string"/>
</model>
</h:head>
<h:body>
<repeat nodeset="/distance/geotrace"/>
</h:body>
</h:html>
6 changes: 6 additions & 0 deletions src/org/javarosa/xpath/expr/XPathFuncExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,16 @@ public Object eval (DataInstance model, EvaluationContext evalContext) {
} else if (name.equals("enclosed-area") || name.equals("area")) {
assertArgsCount(name, args, 1);
List<GeoUtils.LatLong> latLongs = new XPathFuncExprGeo().getGpsCoordinatesFromNodeset(name, argVals[0]);
if (latLongs.size() < 3) {
throw new XPathUnhandledException(String.format("function '%s' requires at least three points.", name));
}
return GeoUtils.calculateAreaOfGPSPolygonOnEarthInSquareMeters(latLongs);
} else if (name.equals("distance")) {
assertArgsCount(name, args, 1);
List<GeoUtils.LatLong> latLongs = new XPathFuncExprGeo().getGpsCoordinatesFromNodeset(name, argVals[0]);
if (latLongs.size() < 2) {
throw new XPathUnhandledException(String.format("function '%s' requires at least two points.", name));
}
return GeoUtils.calculateDistance(latLongs);
} else if (name.equals("digest") && (args.length == 2 || args.length == 3)) {
return DigestAlgorithm.from((String) argVals[1]).digest(
Expand Down
6 changes: 2 additions & 4 deletions src/org/javarosa/xpath/expr/XPathFuncExprGeo.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ List<GeoUtils.LatLong> getGpsCoordinatesFromNodeset(String name, Object argVal)
// Try to determine if the argument is of type GeoShapeData
try {
GeoShapeData geoShapeData = new GeoShapeData().cast(new UncastData(XPathFuncExpr.toString(argList[0])));
if (geoShapeData.points.size() > 2) {
for (GeoPointData point : geoShapeData.points) {
latLongs.add(new GeoUtils.LatLong(point.getPart(0), point.getPart(1)));
}
for (GeoPointData point : geoShapeData.points) {
latLongs.add(new GeoUtils.LatLong(point.getPart(0), point.getPart(1)));
}
} catch (Exception e) {
throw new XPathTypeMismatchException("The function \'" + name + "\' received a value that does not represent GPS coordinates: " + argList[0]);
Expand Down
81 changes: 81 additions & 0 deletions test/org/javarosa/core/util/GeoDistanceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* Copyright 2018 Nafundi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.javarosa.core.util;

import org.javarosa.core.model.FormDef;
import org.javarosa.core.model.data.IAnswerData;
import org.javarosa.core.model.instance.InstanceInitializationFactory;
import org.javarosa.core.model.instance.TreeElement;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.Arrays;

import static org.javarosa.core.model.instance.TreeReference.DEFAULT_MULTIPLICITY;
import static org.javarosa.core.util.GeoUtils.EARTH_EQUATORIAL_CIRCUMFERENCE_METERS;
import static org.javarosa.test.utils.ResourcePathHelper.r;
import static org.javarosa.xform.parse.FormParserHelper.parse;
import static org.junit.Assert.assertEquals;

@RunWith(Enclosed.class)
public class GeoDistanceTest {

@RunWith(Parameterized.class)
public static class ParameterizedPart {
@Parameterized.Parameter(value = 0)
public String geoType;

@Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> data() {
return Arrays.asList(new Object[][]{
{"shape"},
{"trace"},
{"point"},
});
}

/**
* Shows that the distance function can be used with inputs
* <a href="https://opendatakit.github.io/xforms-spec/#fn:distance">as specified</a>.
*/
@Test
public void parsingAndDistanceIsCorrectForThreeGeoTypes() throws Exception {
FormDef formDef = parse(r("distance.xml")).formDef;
formDef.initialize(true, new InstanceInitializationFactory());
TreeElement root = formDef.getMainInstance().getRoot();
IAnswerData distance = root.getChild(geoType + "-result", DEFAULT_MULTIPLICITY).getValue();
double oneDegreeOnEquatorKm = EARTH_EQUATORIAL_CIRCUMFERENCE_METERS / 360;
double ninetyDegreesOnEquatorKm = EARTH_EQUATORIAL_CIRCUMFERENCE_METERS / 4;
assertEquals(oneDegreeOnEquatorKm + ninetyDegreesOnEquatorKm, (Double) distance.getValue(), 1e-7);
}
}

public static class NotParameterizedPart {
@Test
public void testDistanceWithLessThanTwoPoints() throws Exception {
FormDef formDef = parse(r("distance_with_less_than_two_points.xml")).formDef;
try {
formDef.initialize(true, new InstanceInitializationFactory());
} catch (Exception e) {
assertEquals("Error evaluating field 'trace-result': The problem was located in calculate expression for /distance/trace-result\n" +
"XPath evaluation: cannot handle function 'distance' requires at least two points.", e.getMessage());
}
}
}
}
35 changes: 23 additions & 12 deletions test/org/javarosa/core/util/GeoShapeAreaTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,31 @@
public class GeoShapeAreaTest {
private static final Logger logger = LoggerFactory.getLogger(GeoShapeAreaTest.class);

@Test public void testGeoShapeSupportForEnclosedArea() throws Exception {
// Read the form definition
final FormDef formDef = parse(r("area.xml")).formDef;
@Test public void testGeoShapeSupportForEnclosedArea() throws Exception {
// Read the form definition
final FormDef formDef = parse(r("area.xml")).formDef;

// Trigger all calculations
formDef.initialize(true, new InstanceInitializationFactory());
// Trigger all calculations
formDef.initialize(true, new InstanceInitializationFactory());

// Check the results. The data and expected results come from GeoUtilsTest.
TreeElement root = formDef.getMainInstance().getRoot();
// Check the results. The data and expected results come from GeoUtilsTest.
TreeElement root = formDef.getMainInstance().getRoot();

IAnswerData area = root.getChildAt(1).getValue();
assertEquals(151_452, (Double) area.getValue(), 0.5);
IAnswerData area = root.getChildAt(1).getValue();
assertEquals(151_452, (Double) area.getValue(), 0.5);

IAnswerData distance = root.getChildAt(2).getValue();
assertEquals(1_801, (Double) distance.getValue(), 0.5);
}
IAnswerData distance = root.getChildAt(2).getValue();
assertEquals(1_801, (Double) distance.getValue(), 0.5);
}

@Test
public void testAreaWithLessThanThreePoints() throws Exception {
FormDef formDef = parse(r("area_with_less_than_three_points.xml")).formDef;
try {
formDef.initialize(true, new InstanceInitializationFactory());
} catch (Exception e) {
assertEquals("Error evaluating field 'arearesult': The problem was located in calculate expression for /area/arearesult\n" +
"XPath evaluation: cannot handle function 'enclosed-area' requires at least three points.", e.getMessage());
}
}
}
62 changes: 0 additions & 62 deletions test/org/javarosa/core/util/GeoShapeDistanceTest.java

This file was deleted.

0 comments on commit 65c1f02

Please sign in to comment.