use of de.ii.ogcapi.features.geojson.domain.GeoJsonConfiguration in project ldproxy by interactive-instruments.
the class FeaturesFormatJsonFg method getFeatureEncoder.
@Override
public Optional<FeatureTokenEncoder<?>> getFeatureEncoder(FeatureTransformationContext transformationContext, Optional<Locale> language) {
// TODO support language
ImmutableSortedSet<GeoJsonWriter> geoJsonWriters = geoJsonWriterRegistry.getGeoJsonWriters().stream().map(GeoJsonWriter::create).collect(ImmutableSortedSet.toImmutableSortedSet(Comparator.comparingInt(GeoJsonWriter::getSortPriority)));
GeoJsonConfiguration geoJsonConfig = transformationContext.getApiData().getExtension(GeoJsonConfiguration.class, transformationContext.getCollectionId()).get();
ImmutableFeatureTransformationContextGeoJson.Builder transformationContextJsonFgBuilder = ImmutableFeatureTransformationContextGeoJson.builder().from(transformationContext).geoJsonConfig(geoJsonConfig).mediaType(MEDIA_TYPE).prettify(Optional.ofNullable(transformationContext.getOgcApiRequest().getParameters().get("pretty")).filter(value -> Objects.equals(value, "true")).isPresent() || (Objects.requireNonNullElse(geoJsonConfig.getUseFormattedJsonOutput(), false))).debugJson(Optional.ofNullable(transformationContext.getOgcApiRequest().getParameters().get("debug")).filter(value -> Objects.equals(value, "true")).isPresent());
// the GeoJSON "geometry" member is included, if and only if
// - the value of "where" and "geometry" are identical in which case "geometry" is used or
// - the collection is configured to always include the GeoJSON "geometry" member
boolean includePrimaryGeometry = transformationContext.getTargetCrs().equals(transformationContext.getDefaultCrs()) || transformationContext.getApiData().getExtension(JsonFgConfiguration.class, transformationContext.getCollectionId()).map(JsonFgConfiguration::getWhere).map(WhereConfiguration::getAlwaysIncludeGeoJsonGeometry).orElse(false);
transformationContextJsonFgBuilder.suppressPrimaryGeometry(!includePrimaryGeometry).forceDefaultCrs(true);
return Optional.of(new FeatureEncoderGeoJson(transformationContextJsonFgBuilder.build(), geoJsonWriters));
}
use of de.ii.ogcapi.features.geojson.domain.GeoJsonConfiguration in project ldproxy by interactive-instruments.
the class SchemaCacheReturnables method deriveSchema.
@Override
protected JsonSchemaDocument deriveSchema(FeatureSchema schema, OgcApiDataV2 apiData, FeatureTypeConfigurationOgcApi collectionData, Optional<String> schemaUri, VERSION version) {
Optional<PropertyTransformations> propertyTransformations = collectionData.getExtension(GeoJsonConfiguration.class).map(geoJsonConfiguration -> (PropertyTransformations) geoJsonConfiguration);
WithTransformationsApplied schemaTransformer = propertyTransformations.map(WithTransformationsApplied::new).orElse(new WithTransformationsApplied());
SchemaDeriverReturnables schemaDeriverReturnables = new SchemaDeriverReturnables(version, schemaUri, collectionData.getLabel(), Optional.empty(), codelistSupplier.get());
return (JsonSchemaDocument) schema.accept(schemaTransformer).accept(schemaDeriverReturnables);
}
use of de.ii.ogcapi.features.geojson.domain.GeoJsonConfiguration in project ldproxy by interactive-instruments.
the class FeaturesFormatGeoJson method onStartup.
@Override
public ValidationResult onStartup(OgcApi api, MODE apiValidation) {
// no additional operational checks for now, only validation; we can stop, if no validation is requested
if (apiValidation == MODE.NONE)
return ValidationResult.of();
ImmutableValidationResult.Builder builder = ImmutableValidationResult.builder().mode(apiValidation);
Map<String, FeatureSchema> featureSchemas = providers.getFeatureSchemas(api.getData());
// get GeoJSON configurations to process
Map<String, GeoJsonConfiguration> geoJsonConfigurationMap = api.getData().getCollections().entrySet().stream().map(entry -> {
final FeatureTypeConfigurationOgcApi collectionData = entry.getValue();
final GeoJsonConfiguration config = collectionData.getExtension(GeoJsonConfiguration.class).orElse(null);
if (Objects.isNull(config))
return null;
return new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), config);
}).filter(Objects::nonNull).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
for (Map.Entry<String, GeoJsonConfiguration> entry : geoJsonConfigurationMap.entrySet()) {
String collectionId = entry.getKey();
GeoJsonConfiguration config = entry.getValue();
if (config.getNestedObjectStrategy() == GeoJsonConfiguration.NESTED_OBJECTS.FLATTEN && config.getMultiplicityStrategy() != GeoJsonConfiguration.MULTIPLICITY.SUFFIX) {
builder.addStrictErrors(MessageFormat.format("The GeoJSON Nested Object Strategy ''FLATTEN'' in collection ''{0}'' cannot be combined with the Multiplicity Strategy ''{1}''.", collectionId, config.getMultiplicityStrategy()));
} else if (config.getNestedObjectStrategy() == GeoJsonConfiguration.NESTED_OBJECTS.NEST && config.getMultiplicityStrategy() != GeoJsonConfiguration.MULTIPLICITY.ARRAY) {
builder.addStrictErrors(MessageFormat.format("The GeoJSON Nested Object Strategy ''FLATTEN'' in collection ''{0}'' cannot be combined with the Multiplicity Strategy ''{1}''.", collectionId, config.getMultiplicityStrategy()));
}
List<String> separators = ImmutableList.of(".", "_", ":", "/");
if (!separators.contains(config.getSeparator())) {
builder.addStrictErrors(MessageFormat.format("The separator ''{0}'' in collection ''{1}'' is invalid, it must be one of {2}.", config.getSeparator(), collectionId, separators));
}
}
Map<String, Collection<String>> keyMap = geoJsonConfigurationMap.entrySet().stream().map(entry -> new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), entry.getValue().getTransformations().keySet())).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
for (Map.Entry<String, Collection<String>> stringCollectionEntry : featuresCoreValidator.getInvalidPropertyKeys(keyMap, featureSchemas).entrySet()) {
for (String property : stringCollectionEntry.getValue()) {
builder.addStrictErrors(MessageFormat.format("A transformation for property ''{0}'' in collection ''{1}'' is invalid, because the property was not found in the provider schema.", property, stringCollectionEntry.getKey()));
}
}
Set<String> codelists = entityRegistry.getEntitiesForType(Codelist.class).stream().map(Codelist::getId).collect(Collectors.toUnmodifiableSet());
for (Map.Entry<String, GeoJsonConfiguration> entry : geoJsonConfigurationMap.entrySet()) {
String collectionId = entry.getKey();
for (Map.Entry<String, List<PropertyTransformation>> entry2 : entry.getValue().getTransformations().entrySet()) {
String property = entry2.getKey();
for (PropertyTransformation transformation : entry2.getValue()) {
builder = transformation.validate(builder, collectionId, property, codelists);
}
}
}
return builder.build();
}
use of de.ii.ogcapi.features.geojson.domain.GeoJsonConfiguration in project ldproxy by interactive-instruments.
the class GeojsonDataHydrator method getHydratedData.
@Override
public OgcApiDataV2 getHydratedData(OgcApiDataV2 apiData) {
// STRICT: an invalid service definition will not start
if (apiData.getApiValidation() != MODE.STRICT)
return apiData;
OgcApiDataV2 data = apiData;
// get Features Core configurations to process, normalize property names to exclude all square brackets
Map<String, GeoJsonConfiguration> configs = data.getCollections().entrySet().stream().map(entry -> {
// normalize the property references in transformations by removing all
// parts in square brackets
final FeatureTypeConfigurationOgcApi collectionData = entry.getValue();
GeoJsonConfiguration config = collectionData.getExtension(GeoJsonConfiguration.class).orElse(null);
if (Objects.isNull(config))
return null;
final String collectionId = entry.getKey();
final String buildingBlock = config.getBuildingBlock();
if (config.hasDeprecatedTransformationKeys())
config = new Builder().from(config).transformations(config.normalizeTransformationKeys(buildingBlock, collectionId)).build();
return new AbstractMap.SimpleImmutableEntry<>(collectionId, config);
}).filter(Objects::nonNull).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
// update data with changes
data = new ImmutableOgcApiDataV2.Builder().from(data).collections(data.getCollections().entrySet().stream().map(entry -> {
final String collectionId = entry.getKey();
if (!configs.containsKey(collectionId))
return entry;
final GeoJsonConfiguration config = configs.get(collectionId);
final String buildingBlock = config.getBuildingBlock();
return new AbstractMap.SimpleImmutableEntry<String, FeatureTypeConfigurationOgcApi>(collectionId, new ImmutableFeatureTypeConfigurationOgcApi.Builder().from(entry.getValue()).extensions(new ImmutableList.Builder<ExtensionConfiguration>().addAll(entry.getValue().getExtensions().stream().filter(ext -> !ext.getBuildingBlock().equals(buildingBlock)).collect(Collectors.toUnmodifiableList())).add(config).build()).build());
}).collect(ImmutableMap.toImmutableMap(Map.Entry::getKey, Map.Entry::getValue))).build();
return data;
}
Aggregations