Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use OpenAPI tag names to generage Java API interfaces #20

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/services/ogc-features/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
<sourceFolder>src/main/java</sourceFolder>
<library>spring-boot</library>
<reactive>false</reactive>
<useTags>true</useTags>
<useSpringBoot3>true</useSpringBoot3>
<delegatePattern>true</delegatePattern>
<openApiNullable>false</openApiNullable>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,16 @@
import com.camptocamp.opendata.ogc.features.http.codec.shp.ShapefileFeatureCollectionHttpMessageConverter;
import com.camptocamp.opendata.ogc.features.http.codec.xls.Excel2007FeatureCollectionHttpMessageConverter;
import com.camptocamp.opendata.ogc.features.repository.CollectionRepository;
import com.camptocamp.opendata.ogc.features.server.api.CollectionsApiController;
import com.camptocamp.opendata.ogc.features.server.api.CollectionsApiDelegate;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApi;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApiController;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApiDelegate;
import com.camptocamp.opendata.ogc.features.server.api.DataApi;
import com.camptocamp.opendata.ogc.features.server.api.DataApiController;
import com.camptocamp.opendata.ogc.features.server.api.DataApiDelegate;
import com.camptocamp.opendata.ogc.features.server.config.HomeController;
import com.camptocamp.opendata.ogc.features.server.config.SpringDocConfiguration;
import com.camptocamp.opendata.ogc.features.server.impl.CollectionsApiImpl;
import com.camptocamp.opendata.ogc.features.server.impl.CapabilitiesApiImpl;
import com.camptocamp.opendata.ogc.features.server.impl.DataApiImpl;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
Expand Down Expand Up @@ -56,8 +61,23 @@ HomeController homeController() {
}

@Bean
CollectionsApiController collectionsApiController(CollectionsApiDelegate delegate) {
return new CollectionsApiController(delegate);
CapabilitiesApiController capabilitiesApi(CapabilitiesApiDelegate delegate) {
return new CapabilitiesApiController(delegate);
}

@Bean
DataApiController collectionsApiController(DataApiDelegate delegate) {
return new DataApiController(delegate);
}

@Bean
CapabilitiesApiDelegate capabilitiesApiDelegate(CollectionRepository repo) {
return new CapabilitiesApiImpl(repo);
}

@Bean
DataApiDelegate collectionsApiDelegate(CollectionRepository repo) {
return new DataApiImpl(repo);
}

/**
Expand Down Expand Up @@ -95,11 +115,6 @@ CsvFeatureCollectionHttpMessageConverter csvFeatureCollectionHttpMessageConverte
return new CsvFeatureCollectionHttpMessageConverter();
}

@Bean
CollectionsApiDelegate collectionsApiDelegate(CollectionRepository repo) {
return new CollectionsApiImpl(repo);
}

/**
* Filter that replaces the {@literal Accept} request header by the MimeType of
* a matching collection items {@link MimeTypes supported format}, if the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.camptocamp.opendata.ogc.features.server.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import com.camptocamp.opendata.ogc.features.http.codec.MimeTypes;
import com.camptocamp.opendata.ogc.features.model.Collection;
import com.camptocamp.opendata.ogc.features.model.Collections;
import com.camptocamp.opendata.ogc.features.model.Link;
import com.camptocamp.opendata.ogc.features.repository.CollectionRepository;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApiDelegate;

import jakarta.servlet.http.HttpServletRequest;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class CapabilitiesApiImpl implements CapabilitiesApiDelegate {

private final @NonNull CollectionRepository repository;

private @Autowired NativeWebRequest req;

@Override
public Optional<NativeWebRequest> getRequest() {
return Optional.of(req);
}

// TODO: implement
// @Override
// public ResponseEntity<LandingPage> getLandingPage() {
// }

/**
* {@inheritDoc}
*/
@Override
public ResponseEntity<Collections> getCollections() {
List<Collection> collections = repository.getCollections();
Collections body = createCollections(collections);
return ResponseEntity.ok(body);
}

/**
* {@inheritDoc}
*/
@Override
public ResponseEntity<Collection> describeCollection(String collectionId) {
return repository.findCollection(collectionId).map(this::addLinks).map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}

private Collections createCollections(List<Collection> collections) {
Collections cs = new Collections(new ArrayList<>(), collections);
addLinks(cs);
return cs;
}

private Collections addLinks(Collections collections) {
NativeWebRequest request = getRequest().orElseThrow();
HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest();
String basePath = nativeRequest.getRequestURL().toString();
collections.getCollections().forEach(c -> {
String colBase = UriComponentsBuilder.fromUriString(basePath).pathSegment(c.getId()).build().toString();
addLinks(c, colBase);
});
return collections;
}

private Collection addLinks(Collection collection) {
NativeWebRequest request = getRequest().orElseThrow();
HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest();
return addLinks(collection, nativeRequest.getRequestURL().toString());
}

private Collection addLinks(Collection collection, String baseUrl) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(baseUrl);
builder.pathSegment("items");

MimeTypes defFormat = MimeTypes.GeoJSON;
UriComponents itemsc = builder.replaceQueryParam("f", defFormat.getShortName()).build();
Link items = link(itemsc.toString(), "items", defFormat.getMimeType().toString(), collection.getId());
collection.addLinksItem(items);

Arrays.stream(MimeTypes.values()).forEach(m -> {
if (m.supportsItemType(collection.getItemType())) {
String href = builder.replaceQueryParam("f", m.getShortName()).replaceQueryParam("limit", "-1").build()
.toString();
String type = m.getMimeType().toString();
String title = "Bulk download (%s)".formatted(m.getDisplayName());
Link link = link(href, "enclosure", type, title);
collection.addLinksItem(link);
}
});
return collection;
}

private Link link(String href, String rel, String type, String title) {
Link link = new Link(href);
link.setRel(rel);
link.setType(type);
link.setTitle(title);
return link;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.math.BigDecimal;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
Expand All @@ -19,47 +18,27 @@
import com.camptocamp.opendata.model.DataQuery;
import com.camptocamp.opendata.model.GeodataRecord;
import com.camptocamp.opendata.ogc.features.http.codec.MimeTypes;
import com.camptocamp.opendata.ogc.features.model.Collection;
import com.camptocamp.opendata.ogc.features.model.Collections;
import com.camptocamp.opendata.ogc.features.model.FeatureCollection;
import com.camptocamp.opendata.ogc.features.model.Link;
import com.camptocamp.opendata.ogc.features.repository.CollectionRepository;
import com.camptocamp.opendata.ogc.features.server.api.CollectionsApiDelegate;
import com.camptocamp.opendata.ogc.features.server.api.DataApiDelegate;

import jakarta.servlet.http.HttpServletRequest;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class CollectionsApiImpl implements CollectionsApiDelegate {
public class DataApiImpl implements DataApiDelegate {

private final @NonNull CollectionRepository repository;

private @Autowired NativeWebRequest req;

@Override
public Optional<NativeWebRequest> getRequest() {
return Optional.of(req);
}

/**
* {@inheritDoc}
*/
@Override
public ResponseEntity<Collections> getCollections() {
List<Collection> collections = repository.getCollections();
Collections body = createCollections(collections);
return ResponseEntity.ok(body);
}

/**
* {@inheritDoc}
*/
@Override
public ResponseEntity<Collection> describeCollection(String collectionId) {
return repository.findCollection(collectionId).map(this::addLinks).map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}

/**
* {@inheritDoc}
*/
Expand Down Expand Up @@ -122,51 +101,6 @@ private HttpHeaders getFeaturesHeaders(String collectionId) {
return headers;
}

private Collections createCollections(List<Collection> collections) {
Collections cs = new Collections(new ArrayList<>(), collections);
addLinks(cs);
return cs;
}

private Collections addLinks(Collections collections) {
NativeWebRequest request = getRequest().orElseThrow();
HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest();
String basePath = nativeRequest.getRequestURL().toString();
collections.getCollections().forEach(c -> {
String colBase = UriComponentsBuilder.fromUriString(basePath).pathSegment(c.getId()).build().toString();
addLinks(c, colBase);
});
return collections;
}

private Collection addLinks(Collection collection) {
NativeWebRequest request = getRequest().orElseThrow();
HttpServletRequest nativeRequest = (HttpServletRequest) request.getNativeRequest();
return addLinks(collection, nativeRequest.getRequestURL().toString());
}

private Collection addLinks(Collection collection, String baseUrl) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(baseUrl);
builder.pathSegment("items");

MimeTypes defFormat = MimeTypes.GeoJSON;
UriComponents itemsc = builder.replaceQueryParam("f", defFormat.getShortName()).build();
Link items = link(itemsc.toString(), "items", defFormat.getMimeType().toString(), collection.getId());
collection.addLinksItem(items);

Arrays.stream(MimeTypes.values()).forEach(m -> {
if (m.supportsItemType(collection.getItemType())) {
String href = builder.replaceQueryParam("f", m.getShortName()).replaceQueryParam("limit", "-1").build()
.toString();
String type = m.getMimeType().toString();
String title = "Bulk download (%s)".formatted(m.getDisplayName());
Link link = link(href, "enclosure", type, title);
collection.addLinksItem(link);
}
});
return collection;
}

private FeatureCollection addLinks(FeatureCollection fc, DataQuery dataQuery) {
NativeWebRequest request = getRequest().orElseThrow();

Expand Down Expand Up @@ -226,13 +160,12 @@ DataQuery toDataQuery(FeaturesQuery query) {

List<DataQuery.SortBy> sortby = query.sortBy();

DataQuery q = DataQuery.fromUri(URI.create("index://default"))//
return DataQuery.fromUri(URI.create("index://default"))//
.withLayerName(query.getCollectionId())//
.withLimit(query.getLimit())//
.withOffset(query.getOffset())//
.withFilter(query.getFilter())//
.withSortBy(sortby);
return q;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
import com.camptocamp.opendata.ogc.features.http.codec.csv.CsvFeatureCollectionHttpMessageConverter;
import com.camptocamp.opendata.ogc.features.http.codec.shp.ShapefileFeatureCollectionHttpMessageConverter;
import com.camptocamp.opendata.ogc.features.http.codec.xls.Excel2007FeatureCollectionHttpMessageConverter;
import com.camptocamp.opendata.ogc.features.server.api.CollectionsApiController;
import com.camptocamp.opendata.ogc.features.server.api.CollectionsApiDelegate;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApiController;
import com.camptocamp.opendata.ogc.features.server.api.CapabilitiesApiDelegate;
import com.camptocamp.opendata.ogc.features.server.api.DataApiController;
import com.camptocamp.opendata.ogc.features.server.api.DataApiDelegate;
import com.camptocamp.opendata.ogc.features.server.config.HomeController;

class ApiAutoConfigurationTest {
Expand All @@ -27,7 +29,8 @@ class ApiAutoConfigurationTest {
void testExpectedBeans() {
runner.run(context -> {
assertThat(context).hasNotFailed().hasSingleBean(HomeController.class)
.hasSingleBean(CollectionsApiController.class).hasSingleBean(CollectionsApiDelegate.class)
.hasSingleBean(CapabilitiesApiController.class).hasSingleBean(CapabilitiesApiDelegate.class)
.hasSingleBean(DataApiController.class).hasSingleBean(DataApiDelegate.class)
.hasSingleBean(Excel2007FeatureCollectionHttpMessageConverter.class)
.hasSingleBean(ShapefileFeatureCollectionHttpMessageConverter.class)
.hasSingleBean(CsvFeatureCollectionHttpMessageConverter.class);
Expand Down
Loading
Loading