Skip to content

Commit

Permalink
deegree#1752 (#10004) - implemented tunable deegree.gml.parse.recogn…
Browse files Browse the repository at this point in the history
…ize-deprecated-types to enable recognition of deprecated feature collections
  • Loading branch information
lgoltz committed Nov 6, 2024
1 parent f227d2c commit b49c940
Show file tree
Hide file tree
Showing 17 changed files with 7,043 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@
import static org.deegree.commons.tom.gml.GMLObjectCategory.GEOMETRY;
import static org.deegree.commons.tom.gml.GMLObjectCategory.TIME_OBJECT;
import static org.deegree.commons.tom.gml.GMLObjectCategory.TIME_SLICE;
import static org.deegree.commons.utils.TunableParameter.get;
import static org.deegree.commons.xml.CommonNamespaces.GML3_2_NS;
import static org.deegree.commons.xml.CommonNamespaces.GMLNS;
import static org.deegree.commons.xml.CommonNamespaces.ISOAP10GMDNS;
import static org.deegree.commons.xml.CommonNamespaces.ISO_2005_GCO_NS;
import static org.deegree.commons.xml.CommonNamespaces.ISO_2005_GSR_NS;
import static org.deegree.commons.xml.CommonNamespaces.ISO_2005_GSS_NS;
import static org.deegree.commons.xml.CommonNamespaces.ISO_2005_GTS_NS;
import static org.deegree.commons.xml.CommonNamespaces.SMIL_20_NS;
import static org.deegree.commons.xml.CommonNamespaces.SMIL_20_LANGUAGE_NS;
import static org.deegree.commons.xml.CommonNamespaces.SMIL_20_NS;
import static org.deegree.commons.xml.CommonNamespaces.XLNNS;
import static org.deegree.commons.xml.CommonNamespaces.XMLNS;
import static org.deegree.commons.xml.CommonNamespaces.XSNS;
Expand All @@ -63,6 +64,7 @@
import static org.deegree.gml.GMLVersion.GML_31;
import static org.deegree.gml.GMLVersion.GML_32;

import javax.xml.namespace.QName;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -74,8 +76,6 @@
import java.util.SortedSet;
import java.util.TreeSet;

import javax.xml.namespace.QName;

import org.apache.xerces.impl.xs.XSComplexTypeDecl;
import org.apache.xerces.xs.XSAnnotation;
import org.apache.xerces.xs.XSAttributeDeclaration;
Expand Down Expand Up @@ -134,6 +134,20 @@ public class GMLSchemaInfoSet extends XMLSchemaInfoSet {

private static final Logger LOG = LoggerFactory.getLogger(GMLSchemaInfoSet.class);

/**
* This option controls the recognition of GML 3.2 feature collections on the basis of
* FeaturePropertyType.
*
* <code>true</code>: feature types not in GML 3.2 namespace with at least one
* property derived from FeaturePropertyType are recognized as feature collection
*
* <code>false</code> only feature types in GML 3.2 namespace with at least one
* property derived from FeaturePropertyType are recognized as feature collection
*/
protected static final String RECOGNIZE_DEPRECATED_TYPES = "deegree.gml.parse.recognize-deprecated-types";

private static boolean recognizeAllDeprecatedTypesAsFeatureCollection = get(RECOGNIZE_DEPRECATED_TYPES, false);

private static final String GML_PRE_32_NS = CommonNamespaces.GMLNS;

private static final String GML_32_NS = CommonNamespaces.GML3_2_NS;
Expand Down Expand Up @@ -559,20 +573,39 @@ private boolean isGML32FeatureCollection(XSElementDeclaration featureDecl) {
// handle deprecated FeatureCollection types as well (their properties are not
// based on
// AbstractFeatureMemberType, but on FeaturePropertyType)
if (propType.derivedFrom(GML_32_NS, "FeaturePropertyType", (short) (XSConstants.DERIVATION_RESTRICTION
| XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_UNION | XSConstants.DERIVATION_LIST))) {
XSParticle particle = getEnclosingParticle(propDecl);
if (particle != null) {
int maxOccurs = particle.getMaxOccurs();
boolean maxOccursUnbounded = particle.getMaxOccursUnbounded();
return maxOccurs > 1 || maxOccursUnbounded;
boolean deprecatedGml32FeatureCollection = isDeprecatedGml32FeatureCollection(propDecl, propType);
if (deprecatedGml32FeatureCollection) {
if (isGMLNamespace(type.getNamespace())) {
return true;
}
else if (recognizeAllDeprecatedTypesAsFeatureCollection) {
return true;
}
else {
LOG.warn(
"Recognized and ignored feature declaration {{}}{} as deprecated FeatureCollection type. Use tunable {} "
+ "to enable parsing of deprecated feature types not in the GML namespace.",
featureDecl.getNamespace(), featureDecl.getName(), RECOGNIZE_DEPRECATED_TYPES);
}
return true;
}
}
return false;
}

private boolean isDeprecatedGml32FeatureCollection(XSElementDeclaration propDecl, XSTypeDefinition propType) {
if (propType.derivedFrom(GML_32_NS, "FeaturePropertyType", (short) (XSConstants.DERIVATION_RESTRICTION
| XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_UNION | XSConstants.DERIVATION_LIST))) {
XSParticle particle = getEnclosingParticle(propDecl);
if (particle != null) {
int maxOccurs = particle.getMaxOccurs();
boolean maxOccursUnbounded = particle.getMaxOccursUnbounded();
return maxOccurs > 1 || maxOccursUnbounded;
}
return true;
}
return false;
}

private XSParticle getEnclosingParticle(XSElementDeclaration elDecl) {
XSComplexTypeDefinition enclosingDef = elDecl.getEnclosingCTDefinition();
if (enclosingDef != null) {
Expand Down Expand Up @@ -1157,7 +1190,7 @@ public GMLPropertySemantics getTimeSlicePropertySemantics(XSElementDeclaration e

/**
* Returns the {@link GMLObjectCategory} of the given element declaration..
* @param elName element declaration, must not be <code>null</code>
* @param elDecl element declaration, must not be <code>null</code>
* @return category, can be <code>null</code> (element is not a recognized GML object)
*/
public GMLObjectCategory getObjectCategory(final XSElementDeclaration elDecl) {
Expand Down Expand Up @@ -1270,6 +1303,10 @@ public synchronized ObjectPropertyType getCustomElDecl(XSElementDeclaration elDe
return pt;
}

public static void setRecognizeDeprecatedTypes(boolean isRecognizeAllDeprecatedTypesAsFeatureCollection) {
recognizeAllDeprecatedTypesAsFeatureCollection = isRecognizeAllDeprecatedTypesAsFeatureCollection;
}

private void addChildElementDecls(final XSParticle particle, final List<XSTerm> propDecls) {
if (particle != null) {
final XSTerm term = particle.getTerm();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.deegree.gml.GMLStreamReader;
import org.deegree.gml.GMLVersion;
import org.deegree.gml.schema.GMLAppSchemaReader;
import org.deegree.gml.schema.GMLSchemaInfoSet;
import org.deegree.time.primitive.TimePeriod;
import org.junit.Assert;
import org.junit.Test;
Expand Down Expand Up @@ -351,6 +352,7 @@ public void testParsingCustomProps() throws XMLStreamException, FactoryConfigura
public void testINSPIREAddresses1() throws XMLStreamException, FactoryConfigurationError, IOException,
ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException,
XMLParsingException, UnknownCRSException, ReferenceResolvingException {
GMLSchemaInfoSet.setRecognizeDeprecatedTypes(true);

URL schemaURL = GMLFeatureReaderTest.class.getResource("../inspire/schema/Addresses.xsd");
GMLAppSchemaReader adapter = new GMLAppSchemaReader(GML_32, null, schemaURL.toString());
Expand All @@ -369,6 +371,7 @@ public void testINSPIREAddresses1() throws XMLStreamException, FactoryConfigurat
public void testINSPIREAddresses1Stream() throws XMLStreamException, FactoryConfigurationError, IOException,
ClassCastException, ClassNotFoundException, InstantiationException, IllegalAccessException,
XMLParsingException, UnknownCRSException, ReferenceResolvingException {
GMLSchemaInfoSet.setRecognizeDeprecatedTypes(true);

URL schemaURL = GMLFeatureReaderTest.class.getResource("../inspire/schema/Addresses.xsd");
GMLAppSchemaReader adapter = new GMLAppSchemaReader(GML_32, null, schemaURL.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,13 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.List;

import javax.xml.namespace.QName;
import java.util.List;

import org.apache.xerces.impl.xs.XSAttributeDecl;
import org.apache.xerces.xs.XSAttributeDeclaration;
import org.apache.xerces.xs.XSAttributeUse;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSTypeDefinition;
import org.deegree.commons.tom.gml.GMLObjectType;
import org.deegree.commons.tom.gml.property.PropertyType;
import org.deegree.commons.utils.test.TestProperties;
Expand Down Expand Up @@ -474,6 +471,45 @@ public void testIncludedGml321BaseSchemaIncludesGmlIdCorrigendum()
assertFalse(attrUse.getRequired());
}

@Test
public void testGml32DeprecatedFeatureCollections()
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
GMLSchemaInfoSet.setRecognizeDeprecatedTypes(true);
String schemaURL = this.getClass()
.getResource("../inspire/schema/geophysicsCore/GeophysicsCore.xsd")
.toString();
GMLAppSchemaReader adapter = new GMLAppSchemaReader(null, null, schemaURL);
AppSchema schema = adapter.extractAppSchema();
FeatureType geophProfile = schema
.getFeatureType(new QName("http://inspire.ec.europa.eu/schemas/ge_gp/4.0", "GeophProfile"));
assertTrue(geophProfile instanceof FeatureCollectionType);
FeatureType campaign = schema
.getFeatureType(new QName("http://inspire.ec.europa.eu/schemas/ge_gp/4.0", "Campaign"));
assertTrue(campaign instanceof FeatureCollectionType);

FeatureType gml32FeatureCollection = schema.getFeatureType(new QName(GML3_2_NS, "FeatureCollection"));
assertTrue(gml32FeatureCollection instanceof FeatureCollectionType);
}

@Test
public void testGml32DeprecatedFeatureCollections_recognitionDisabled()
throws ClassNotFoundException, InstantiationException, IllegalAccessException {
String schemaURL = this.getClass()
.getResource("../inspire/schema/geophysicsCore/GeophysicsCore.xsd")
.toString();
GMLAppSchemaReader adapter = new GMLAppSchemaReader(null, null, schemaURL);
AppSchema schema = adapter.extractAppSchema();
FeatureType geophProfile = schema
.getFeatureType(new QName("http://inspire.ec.europa.eu/schemas/ge_gp/4.0", "GeophProfile"));
assertFalse(geophProfile instanceof FeatureCollectionType);
FeatureType campaign = schema
.getFeatureType(new QName("http://inspire.ec.europa.eu/schemas/ge_gp/4.0", "Campaign"));
assertFalse(campaign instanceof FeatureCollectionType);

FeatureType gml32FeatureCollection = schema.getFeatureType(new QName(GML3_2_NS, "FeatureCollection"));
assertTrue(gml32FeatureCollection instanceof FeatureCollectionType);
}

private void assertPropertyType(GMLObjectType geometryDecl, int propDeclIdx, QName propName, int minOccurs,
int maxOccurs) {
PropertyType pt = geometryDecl.getPropertyDeclarations().get(propDeclIdx);
Expand Down
Loading

0 comments on commit b49c940

Please sign in to comment.