Skip to content

Commit

Permalink
GEOS-8935: introduced new coordinates formatting options for WFS GML …
Browse files Browse the repository at this point in the history
…output formats
  • Loading branch information
mbarto committed Sep 27, 2018
1 parent 3295633 commit 2472f25
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 29 deletions.
18 changes: 18 additions & 0 deletions src/main/src/main/java/org/geoserver/catalog/FeatureTypeInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,24 @@ public interface FeatureTypeInfo extends ResourceInfo {
*/
void setNumDecimals(int numDecimals);

/**
* If numbers float should be formatted right-padding them with zeros.
*
* @return
*/
boolean getPadWithZeros();

/**
* Sets wether float numbers should be formatted right-padding them with zeros.
*
* @param padWithZeros
*/
void setPadWithZeros(boolean padWithZeros);

boolean getForcedDecimal();

void setForcedDecimal(boolean forcedDecimal);

/**
* Tolerance used to linearize this feature type, as an absolute value expressed in the
* geometries own CRS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public class FeatureTypeInfoImpl extends ResourceInfoImpl implements FeatureType

protected int maxFeatures;
protected int numDecimals;
protected boolean padWithZeros;
protected boolean forcedDecimal;

protected List<AttributeTypeInfo> attributes = new ArrayList<AttributeTypeInfo>();
protected List<String> responseSRS = new ArrayList<String>();
Expand Down Expand Up @@ -253,4 +255,24 @@ public boolean getEncodeMeasures() {
public void setEncodeMeasures(boolean encodeMeasures) {
this.encodeMeasures = encodeMeasures;
}

@Override
public boolean getPadWithZeros() {
return padWithZeros;
}

@Override
public void setPadWithZeros(boolean padWithZeros) {
this.padWithZeros = padWithZeros;
}

@Override
public boolean getForcedDecimal() {
return forcedDecimal;
}

@Override
public void setForcedDecimal(boolean forcedDecimal) {
this.forcedDecimal = forcedDecimal;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -334,4 +334,24 @@ public boolean getEncodeMeasures() {
public void setEncodeMeasures(boolean encodeMeasures) {
delegate.setEncodeMeasures(encodeMeasures);
}

@Override
public boolean getPadWithZeros() {
return delegate.getPadWithZeros();
}

@Override
public void setPadWithZeros(boolean padWithZeros) {
delegate.setPadWithZeros(padWithZeros);
}

@Override
public boolean getForcedDecimal() {
return delegate.getForcedDecimal();
}

@Override
public void setForcedDecimal(boolean forcedDecimal) {
delegate.setForcedDecimal(forcedDecimal);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ <h3><wicket:message key="wfsSettings">WFS Settings</wicket:message></h3>
<div wicket:id="maxDecimalsBorder">
<input id="maxDecimals" class="text" wicket:id="maxDecimals" type="text"></input>
</div>
<label for="padWithZeros"><wicket:message key="padWithZeros">Right-pad decimals with zeros</wicket:message></label>
<div wicket:id="padWithZerosBorder">
<input id="padWithZeros" wicket:id="padWithZeros" type="checkbox"></input>
</div>
<label for="forcedDecimal"><wicket:message key="forcedDecimal">Force decimals, don't use scientific notation</wicket:message></label>
<div wicket:id="forcedDecimalBorder">
<input id="forcedDecimal" wicket:id="forcedDecimal" type="checkbox"></input>
</div>
</li>
</ul>
</fieldset>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ public WFSLayerConfig(String id, IModel<LayerInfo> model) {
Border mdb = new FormComponentFeedbackBorder("maxDecimalsBorder");
mdb.add(maxDecimals);
add(mdb);
CheckBox padWithZeros =
new CheckBox(
"padWithZeros", new PropertyModel<Boolean>(model, "resource.padWithZeros"));
Border pwzb = new FormComponentFeedbackBorder("padWithZerosBorder");
pwzb.add(padWithZeros);
add(pwzb);

CheckBox forcedDecimal =
new CheckBox(
"forcedDecimal",
new PropertyModel<Boolean>(model, "resource.forcedDecimal"));
Border fdb = new FormComponentFeedbackBorder("forcedDecimalBorder");
fdb.add(forcedDecimal);
add(fdb);
CheckBox skipNumberMatched =
new CheckBox(
"skipNumberMatched",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ WFSAdminPage.otherSRS.message=A comma separated list of EPSG codes, e.g. 4326,38
response.

WFSLayerConfig.maxDecimals=Maximum number of decimals
WFSLayerConfig.padWithZeros=Right-pad decimals with zeros
WFSLayerConfig.forcedDecimal=Forced decimal notation, don't use scientific notation
WFSLayerConfig.perReqFeatureLimit=Per-Request Feature Limit
WFSLayerConfig.wfsSettings=WFS Settings
WFSLayerConfig.featureSettings=Feature Settings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,50 @@ public void testEncodeMeasuresCheckbox() {
ft.submit();
tester.assertModelValue("form:panel:encodeMeasures", false);
}

@Test
public void testForceDecimalCheckbox() {
// get a test layer and instantiate the model
final LayerInfo layer = getCatalog().getLayerByName(MockData.PONDS.getLocalPart());
Model<LayerInfo> model = new Model<>(layer);
FormTestPage page =
new FormTestPage((ComponentBuilder) id -> new WFSLayerConfig(id, model));
// let's start the page and check that the components are correctly instantiated
tester.startPage(page);
tester.assertRenderedPage(FormTestPage.class);
tester.assertComponent("form", Form.class);
// check that the checkbox is available
tester.assertComponent(
"form:panel:forcedDecimalBorder:forcedDecimalBorder_body:forcedDecimal",
CheckBox.class);
// unselect the checkbox, no measures should be selected
FormTester ft = tester.newFormTester("form");
ft.setValue("panel:forcedDecimalBorder:forcedDecimalBorder_body:forcedDecimal", true);
ft.submit();
tester.assertModelValue(
"form:panel:forcedDecimalBorder:forcedDecimalBorder_body:forcedDecimal", true);
}

@Test
public void testPadWithZerosCheckbox() {
// get a test layer and instantiate the model
final LayerInfo layer = getCatalog().getLayerByName(MockData.PONDS.getLocalPart());
Model<LayerInfo> model = new Model<>(layer);
FormTestPage page =
new FormTestPage((ComponentBuilder) id -> new WFSLayerConfig(id, model));
// let's start the page and check that the components are correctly instantiated
tester.startPage(page);
tester.assertRenderedPage(FormTestPage.class);
tester.assertComponent("form", Form.class);
// check that the checkbox is available
tester.assertComponent(
"form:panel:padWithZerosBorder:padWithZerosBorder_body:padWithZeros",
CheckBox.class);
// unselect the checkbox, no measures should be selected
FormTester ft = tester.newFormTester("form");
ft.setValue("panel:padWithZerosBorder:padWithZerosBorder_body:padWithZeros", true);
ft.submit();
tester.assertModelValue(
"form:panel:padWithZerosBorder:padWithZerosBorder_body:padWithZeros", true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import org.geoserver.catalog.Catalog;
Expand Down Expand Up @@ -199,24 +200,32 @@ public void write(Object value, OutputStream output, Operation operation)
}
}

private <T> T getFeatureTypeInfoProperty(
Catalog catalog, FeatureCollection features, Function<FeatureTypeInfo, T> callback) {
FeatureType featureType = features.getSchema();

ResourceInfo meta = catalog.getResourceByName(featureType.getName(), ResourceInfo.class);
if (meta instanceof FeatureTypeInfo) {
FeatureTypeInfo fti = (FeatureTypeInfo) meta;
return callback.apply(fti);
}
return null;
}

protected int getNumDecimals(List featureCollections, GeoServer geoServer, Catalog catalog) {
int numDecimals = -1;
for (int i = 0; i < featureCollections.size(); i++) {
FeatureCollection features = (FeatureCollection) featureCollections.get(i);
FeatureType featureType = features.getSchema();

ResourceInfo meta =
catalog.getResourceByName(featureType.getName(), ResourceInfo.class);
Integer ftiDecimals =
getFeatureTypeInfoProperty(
catalog,
(FeatureCollection) featureCollections.get(i),
fti -> fti.getNumDecimals());

// track num decimals, in cases where the query has multiple types we choose the max
// of all the values (same deal as above, might not be a vector due to GetFeatureInfo
// reusing this)
if (meta instanceof FeatureTypeInfo) {
int ftiDecimals = ((FeatureTypeInfo) meta).getNumDecimals();
if (ftiDecimals > 0) {
numDecimals =
numDecimals == -1 ? ftiDecimals : Math.max(numDecimals, ftiDecimals);
}
if (ftiDecimals != null && ftiDecimals > 0) {
numDecimals = numDecimals == -1 ? ftiDecimals : Math.max(numDecimals, ftiDecimals);
}
}

Expand All @@ -229,6 +238,38 @@ protected int getNumDecimals(List featureCollections, GeoServer geoServer, Catal
return numDecimals;
}

protected boolean getPadWithZeros(
List featureCollections, GeoServer geoServer, Catalog catalog) {
boolean padWithZeros = false;
for (int i = 0; i < featureCollections.size(); i++) {
Boolean pad =
getFeatureTypeInfoProperty(
catalog,
(FeatureCollection) featureCollections.get(i),
fti -> fti.getPadWithZeros());
if (pad != null && pad.booleanValue()) {
padWithZeros = true;
}
}
return padWithZeros;
}

protected boolean getForcedDecimal(
List featureCollections, GeoServer geoServer, Catalog catalog) {
boolean forcedDecimal = false;
for (int i = 0; i < featureCollections.size(); i++) {
Boolean forced =
getFeatureTypeInfoProperty(
catalog,
(FeatureCollection) featureCollections.get(i),
fti -> fti.getForcedDecimal());
if (forced != null && forced.booleanValue()) {
forcedDecimal = true;
}
}
return forcedDecimal;
}

/**
* Helper method that checks if coordinates measured values should be encoded for the provided
* feature collections. By default coordinates measures are not encoded.
Expand All @@ -240,18 +281,14 @@ protected int getNumDecimals(List featureCollections, GeoServer geoServer, Catal
protected boolean encodeMeasures(List featureCollections, Catalog catalog) {
boolean encodeMeasures = true;
for (int i = 0; i < featureCollections.size(); i++) {
// get the feature type of the current collection
FeatureCollection features = (FeatureCollection) featureCollections.get(i);
FeatureType featureType = features.getSchema();
ResourceInfo resourceInfo =
catalog.getResourceByName(featureType.getName(), ResourceInfo.class);
// let's see if this is a feature type
if (resourceInfo instanceof FeatureTypeInfo) {
FeatureTypeInfo featureTypeInfo = (FeatureTypeInfo) resourceInfo;
if (!featureTypeInfo.getEncodeMeasures()) {
// no measures should be encoded
encodeMeasures = false;
}
Boolean measures =
getFeatureTypeInfoProperty(
catalog,
(FeatureCollection) featureCollections.get(i),
fti -> fti.getEncodeMeasures());
if (measures != null && !measures.booleanValue()) {
// no measures should be encoded
encodeMeasures = false;
}
}
return encodeMeasures;
Expand Down
12 changes: 12 additions & 0 deletions src/wfs/src/main/java/org/geoserver/wfs/xml/GML2OutputFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ public void prepare(
// one type, we really need to set it on the feature level
int srs = -1;
int numDecimals = -1;
boolean padWithZeros = false;
boolean forcedDecimal = false;
for (int i = 0; i < results.getFeature().size(); i++) {
// FeatureResults features = (FeatureResults) f.next();
FeatureCollection features = (FeatureCollection) results.getFeature().get(i);
Expand Down Expand Up @@ -175,6 +177,14 @@ public void prepare(
numDecimals =
numDecimals == -1 ? ftiDecimals : Math.max(numDecimals, ftiDecimals);
}
boolean pad = ((FeatureTypeInfo) meta).getPadWithZeros();
if (pad) {
padWithZeros = true;
}
boolean force = ((FeatureTypeInfo) meta).getForcedDecimal();
if (force) {
forcedDecimal = true;
}
}
}

Expand All @@ -188,6 +198,8 @@ public void prepare(

transformer.setIndentation(wfs.isVerbose() ? INDENT_SIZE : (NO_FORMATTING));
transformer.setNumDecimals(numDecimals);
transformer.setPadWithZeros(padWithZeros);
transformer.setForceDecimalEncoding(forcedDecimal);
transformer.setFeatureBounding(wfs.isFeatureBounding());
transformer.setCollectionBounding(wfs.isFeatureBounding());
transformer.setEncoding(Charset.forName(settings.getCharset()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,22 @@ protected GeometryTranslator createGeometryTranslator(ContentHandler handler) {
}

protected GeometryTranslator createGeometryTranslator(
ContentHandler handler, int numDecimals) {
return new GML3GeometryTranslator(handler, numDecimals);
ContentHandler handler,
int numDecimals,
boolean padWithZeros,
boolean forceDecimalEncoding) {
return new GML3GeometryTranslator(
handler, numDecimals, padWithZeros, forceDecimalEncoding);
}

protected GeometryTranslator createGeometryTranslator(
ContentHandler handler, int numDecimals, boolean useDummyZ) {
return new GML3GeometryTranslator(handler, numDecimals, useDummyZ);
ContentHandler handler,
int numDecimals,
boolean padWithZeros,
boolean forceDecimalEncoding,
boolean useDummyZ) {
return new GML3GeometryTranslator(
handler, numDecimals, padWithZeros, forceDecimalEncoding, useDummyZ);
}

protected Attributes encodeFeatureId(SimpleFeature f) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,23 @@ public GML3GeometryTranslator(ContentHandler handler, int numDecimals) {
super(handler, numDecimals);
}

public GML3GeometryTranslator(
ContentHandler handler,
int numDecimals,
boolean padWithZeros,
boolean forceDecimalEncoding,
boolean useDummyZ) {
super(handler, numDecimals, padWithZeros, forceDecimalEncoding, useDummyZ);
}

public GML3GeometryTranslator(
ContentHandler handler,
int numDecimals,
boolean padWithZeros,
boolean forceDecimalEncoding) {
super(handler, numDecimals, padWithZeros, forceDecimalEncoding);
}

protected String boxName() {
return "Envelope";
}
Expand Down

0 comments on commit 2472f25

Please sign in to comment.