/*
* This is part of Geomajas, a GIS framework, http://www.geomajas.org/.
*
* Copyright 2008-2015 Geosparc nv, http://www.geosparc.com/, Belgium.
*
* The program is available in open source according to the GNU Affero
* General Public License. All contributions in this program are covered
* by the Geomajas Contributors License Agreement. For full licensing
* details, see LICENSE.txt in the project root.
*/
package org.geomajas.gwt2.plugin.wfs.server.command;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import net.opengis.wfs.FeatureTypeListType;
import net.opengis.wfs.FeatureTypeType;
import net.opengis.wfs.WFSCapabilitiesType;
import org.geomajas.command.CommandHasRequest;
import org.geomajas.geometry.Bbox;
import org.geomajas.global.ExceptionCode;
import org.geomajas.global.GeomajasException;
import org.geomajas.gwt2.plugin.wfs.client.service.WfsService.WfsVersion;
import org.geomajas.gwt2.plugin.wfs.server.command.dto.WfsGetCapabilitiesRequest;
import org.geomajas.gwt2.plugin.wfs.server.command.dto.WfsGetCapabilitiesResponse;
import org.geomajas.gwt2.plugin.wfs.server.command.factory.URLBuilder;
import org.geomajas.gwt2.plugin.wfs.server.command.factory.WfsDataStoreFactory;
import org.geomajas.gwt2.plugin.wfs.server.command.factory.WfsHttpClientFactory;
import org.geomajas.gwt2.plugin.wfs.server.command.factory.impl.DefaultWfsDataStoreFactory;
import org.geomajas.gwt2.plugin.wfs.server.command.factory.impl.DefaultWfsHttpClientFactory;
import org.geomajas.gwt2.plugin.wfs.server.dto.WfsFeatureTypeDto;
import org.geomajas.gwt2.plugin.wfs.server.dto.WfsFeatureTypeListDto;
import org.geomajas.gwt2.plugin.wfs.server.dto.WfsGetCapabilitiesDto;
import org.geomajas.service.DtoConverterService;
import org.geotools.data.wfs.WFSDataStore;
import org.geotools.data.wfs.WFSDataStoreFactory;
import org.geotools.data.wfs.internal.WFSGetCapabilities;
import org.geotools.data.wfs.internal.v1_x.FeatureTypeInfoImpl;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Command that issues WFS GetCapabilities request.
*
* @author Jan De Moerloose
*
*/
@Component(WfsGetCapabilitiesRequest.COMMAND_NAME)
public class WfsGetCapabilitiesCommand implements
CommandHasRequest<WfsGetCapabilitiesRequest, WfsGetCapabilitiesResponse> {
private final Logger log = LoggerFactory.getLogger(WfsGetCapabilitiesCommand.class);
@Autowired
private DtoConverterService dtoConverterService;
private WfsDataStoreFactory dataStoreFactory;
private WfsHttpClientFactory httpClientFactory;
public WfsGetCapabilitiesCommand() {
dataStoreFactory = new DefaultWfsDataStoreFactory();
httpClientFactory = new DefaultWfsHttpClientFactory();
}
public void setDataStoreFactory(WfsDataStoreFactory dataStoreFactory) {
this.dataStoreFactory = dataStoreFactory;
}
public void setHttpClientFactory(WfsHttpClientFactory httpClientFactory) {
this.httpClientFactory = httpClientFactory;
}
@Override
public void execute(WfsGetCapabilitiesRequest request, WfsGetCapabilitiesResponse response)
throws GeomajasException {
try {
String sourceUrl = request.getBaseUrl();
URL targetUrl = httpClientFactory.getTargetUrl(sourceUrl);
// Create a WFS GetCapabilities URL:
URL url = URLBuilder.createWfsURL(targetUrl, request.getVersion(), "GetCapabilities");
String capa = url.toExternalForm();
Map<String, Serializable> connectionParameters = new HashMap<String, Serializable>();
connectionParameters.put(WFSDataStoreFactory.URL.key, capa);
connectionParameters.put(WFSDataStoreFactory.TIMEOUT.key, 10000);
if (request.getStrategy() != null) {
connectionParameters.put(WFSDataStoreFactory.WFS_STRATEGY.key, request.getStrategy());
}
WFSDataStore wfs = dataStoreFactory.createDataStore(connectionParameters,
httpClientFactory.create(sourceUrl));
// The following uses internal geotools classes, anyone knows a more generic way to get the feature types
// ???
WfsFeatureTypeListDto wfsFeatureTypeListDto = null;
String vs = wfs.getWfsClient().getInfo().getVersion();
WfsVersion version = WfsVersion.fromString(vs);
switch (version) {
case V1_0_0:
case V1_1_0:
wfsFeatureTypeListDto = create1xxFeatureTypeList(wfs);
break;
case V2_0_0:
default:
wfsFeatureTypeListDto = create200FeatureTypeList(wfs);
break;
}
WfsGetCapabilitiesDto getCapabilitiesDto = new WfsGetCapabilitiesDto(wfsFeatureTypeListDto);
response.setGetCapabilitiesDto(getCapabilitiesDto);
} catch (Exception e) {
log.error("GetCapabilities failed for " + request.getBaseUrl(), e);
throw new GeomajasException(ExceptionCode.UNEXPECTED_PROBLEM, e.getMessage());
}
}
private WfsFeatureTypeListDto create1xxFeatureTypeList(WFSDataStore wfs) {
WFSGetCapabilities capabilities = wfs.getWfsClient().getCapabilities();
WFSCapabilitiesType caps = (WFSCapabilitiesType) capabilities.getParsedCapabilities();
FeatureTypeListType featureTypeListType = caps.getFeatureTypeList();
WfsFeatureTypeListDto featureTypeListDto = new WfsFeatureTypeListDto();
for (Object o : featureTypeListType.getFeatureType()) {
FeatureTypeInfoImpl featureType = new FeatureTypeInfoImpl((FeatureTypeType) o);
WfsFeatureTypeDto wfsFeatureTypeDto = new WfsFeatureTypeDto();
// The name needs a prefix to be unique, use the literal name element here
String prefix = ((FeatureTypeType) o).getName().getPrefix();
String localPart = ((FeatureTypeType) o).getName().getLocalPart();
String fullName = (prefix == null || prefix.isEmpty()) ? localPart : prefix + ":" + localPart;
wfsFeatureTypeDto.setName(fullName);
wfsFeatureTypeDto.setAbstract(featureType.getAbstract());
wfsFeatureTypeDto.setTitle(featureType.getTitle());
wfsFeatureTypeDto.setDefaultCrs(featureType.getDefaultSRS());
ReferencedEnvelope bbox = featureType.getWGS84BoundingBox();
if (bbox != null) {
wfsFeatureTypeDto.setWGS84BoundingBox(dtoConverterService.toDto(bbox));
} else {
wfsFeatureTypeDto.setWGS84BoundingBox(new Bbox(-180, -90, 360, 180));
}
wfsFeatureTypeDto.setKeywords(new ArrayList<String>(featureType.getKeywords()));
featureTypeListDto.add(wfsFeatureTypeDto);
}
return featureTypeListDto;
}
private WfsFeatureTypeListDto create200FeatureTypeList(WFSDataStore wfs) {
WFSGetCapabilities capabilities = wfs.getWfsClient().getCapabilities();
net.opengis.wfs20.WFSCapabilitiesType caps = (net.opengis.wfs20.WFSCapabilitiesType) capabilities
.getParsedCapabilities();
net.opengis.wfs20.FeatureTypeListType featureTypeListType = caps.getFeatureTypeList();
WfsFeatureTypeListDto featureTypeListDto = new WfsFeatureTypeListDto();
for (Object o : featureTypeListType.getFeatureType()) {
org.geotools.data.wfs.internal.v2_0.FeatureTypeInfoImpl featureType =
new org.geotools.data.wfs.internal.v2_0.FeatureTypeInfoImpl(
(net.opengis.wfs20.FeatureTypeType) o);
WfsFeatureTypeDto wfsFeatureTypeDto = new WfsFeatureTypeDto();
// The name needs a prefix to be unique, use the literal name element here
String prefix = featureType.getQName().getPrefix();
String localPart = featureType.getQName().getLocalPart();
String fullName = (prefix == null || prefix.isEmpty()) ? localPart : prefix + ":" + localPart;
wfsFeatureTypeDto.setName(fullName);
wfsFeatureTypeDto.setAbstract(featureType.getAbstract());
wfsFeatureTypeDto.setTitle(featureType.getTitle());
wfsFeatureTypeDto.setDefaultCrs(featureType.getDefaultSRS());
ReferencedEnvelope bbox = featureType.getWGS84BoundingBox();
if (bbox != null) {
wfsFeatureTypeDto.setWGS84BoundingBox(dtoConverterService.toDto(bbox));
} else {
wfsFeatureTypeDto.setWGS84BoundingBox(new Bbox(-180, -90, 360, 180));
}
wfsFeatureTypeDto.setKeywords(new ArrayList<String>(featureType.getKeywords()));
featureTypeListDto.add(wfsFeatureTypeDto);
}
return featureTypeListDto;
}
@Override
public WfsGetCapabilitiesRequest getEmptyCommandRequest() {
return new WfsGetCapabilitiesRequest();
}
@Override
public WfsGetCapabilitiesResponse getEmptyCommandResponse() {
return new WfsGetCapabilitiesResponse();
}
}