/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wfs.xml;
import org.eclipse.xsd.XSDFactory;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.impl.XSDSchemaImpl;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.ows.URLMangler.URLType;
import org.geoserver.ows.util.ResponseUtils;
import org.geotools.xml.XSD;
import org.opengis.feature.simple.SimpleFeatureType;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class ApplicationSchemaXSD1 extends XSD {
FeatureTypeSchemaBuilder schemaBuilder;
Map<String,Set<FeatureTypeInfo>> featureTypes;
String baseURL;
public ApplicationSchemaXSD1(FeatureTypeSchemaBuilder schemaBuilder) {
this(schemaBuilder, Collections.emptyMap());
}
public ApplicationSchemaXSD1(FeatureTypeSchemaBuilder schemaBuilder,
Map<String,Set<FeatureTypeInfo>> featureTypes) {
this.schemaBuilder = schemaBuilder;
this.featureTypes = featureTypes;
}
public void setBaseURL(String baseURL) {
this.baseURL = baseURL;
}
public String getBaseURL() {
return baseURL;
}
public void setResources(Map<String, Set<ResourceInfo>> resources) {
Map<String, Set<FeatureTypeInfo>> featureTypes = new HashMap<>();
for (Map.Entry<String, Set<ResourceInfo>> entry : resources.entrySet()) {
Set<FeatureTypeInfo> fts = new HashSet<>();
for(ResourceInfo ri : entry.getValue()) {
if(ri instanceof FeatureTypeInfo) {
fts.add((FeatureTypeInfo) ri);
}
}
if(!fts.isEmpty()) {
featureTypes.put(entry.getKey(), fts);
}
}
this.featureTypes = featureTypes;
}
public Map<String, Set<FeatureTypeInfo>> getFeatureTypes() {
return featureTypes;
}
@Override
public String getNamespaceURI() {
if (featureTypes.size() == 1) {
return featureTypes.keySet().iterator().next();
}
//TODO: return xsd namespace?
return null;
}
@Override
public String getSchemaLocation() {
StringBuilder sb = new StringBuilder();
for (Set<FeatureTypeInfo> fts : featureTypes.values()) {
for (FeatureTypeInfo ft : fts) {
sb.append(ft.getPrefixedName()).append(",");
}
}
sb.setLength(sb.length() - 1);
HashMap kvp = new HashMap();
kvp.putAll(schemaBuilder.getDescribeFeatureTypeParams());
kvp.put("typename", sb.toString());
return ResponseUtils.buildURL(baseURL, "wfs", kvp, URLType.SERVICE);
}
@Override
protected XSDSchema buildSchema() throws IOException {
FeatureTypeInfo[] types = this.featureTypes.values().stream()
.flatMap(Collection::stream).toArray(FeatureTypeInfo[]::new);
XSDSchema schema;
if (containsComplexTypes(types)) {
// we have complex features so we add all the available catalog feature types
schema = schemaBuilder.build(new FeatureTypeInfo[0], baseURL, true, true);
schemaBuilder.addApplicationTypes(schema);
} else {
// simple feature so we add only the feature types we need
schema = schemaBuilder.build(types, baseURL, true, true);
}
// add an explicit dependency on WFS 1.0.0 schema
return importWfsSchema(schema);
}
/**
* Checks if the provided feature types contains complex types.
*/
private static boolean containsComplexTypes(FeatureTypeInfo[] featureTypes) {
for (FeatureTypeInfo featureType : featureTypes) {
try {
if(!(featureType.getFeatureType() instanceof SimpleFeatureType)) {
return true;
}
}
catch(Exception exception) {
// ignore the broken feature type
}
}
return false;
}
/**
* Imports the WFS 1.0.0 schema as a dependency.
*/
private static XSDSchema importWfsSchema(XSDSchema schema) throws IOException {
XSDSchema wfsSchema = org.geotools.wfs.v1_1.WFS.getInstance().getSchema();
if (wfsSchema == null || !(wfsSchema instanceof XSDSchemaImpl)) {
return schema;
}
XSDImport wfsImport = XSDFactory.eINSTANCE.createXSDImport();
wfsImport.setNamespace(org.geotools.wfs.v1_1.WFS.NAMESPACE);
wfsImport.setResolvedSchema(wfsSchema);
schema.getContents().add(wfsImport);
schema.getQNamePrefixToNamespaceMap().put("wfs", org.geotools.wfs.v1_1.WFS.NAMESPACE);
synchronized (wfsSchema.eAdapters()) {
((XSDSchemaImpl) wfsSchema).imported(wfsImport);
}
return schema;
}
}