Created new version of the schema

This commit is contained in:
Luca Frosini 2023-03-14 11:58:52 +01:00
parent 628149bf28
commit dbd7d51d1b
11 changed files with 8799 additions and 11 deletions

17
pom.xml
View File

@ -12,7 +12,7 @@
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>gcat</artifactId>
<packaging>war</packaging>
<version>2.5.0</version>
<version>2.5.1-SNAPSHOT</version>
<name>gCube Catalogue (gCat) Service</name>
<description>
This service allows any client to publish on the gCube Catalogue.
@ -35,7 +35,7 @@
<dependency>
<groupId>org.gcube.distribution</groupId>
<artifactId>gcube-smartgears-bom</artifactId>
<version>2.3.0</version>
<version>2.3.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@ -62,7 +62,7 @@
<dependency>
<groupId>org.gcube.data-catalogue</groupId>
<artifactId>gcat-api</artifactId>
<version>[2.3.2, 3.0.0-SNAPSHOT)</version>
<version>[2.3.2-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.social-networking</groupId>
@ -72,7 +72,7 @@
<dependency>
<groupId>org.gcube.common</groupId>
<artifactId>authorization-utils</artifactId>
<version>[2.1.0, 3.0.0-SNAPSHOT)</version>
<version>[2.1.0-SNAPSHOT, 3.0.0-SNAPSHOT)</version>
</dependency>
<dependency>
<groupId>org.gcube.common</groupId>
@ -337,6 +337,15 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -1,18 +1,33 @@
package org.gcube.gcat.profile;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.gcube.gcat.ContextTest;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.gcube.com.fasterxml.jackson.databind.JsonNode;
import org.gcube.com.fasterxml.jackson.databind.node.ArrayNode;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
public class ProfileTest extends ContextTest {
@ -74,15 +89,41 @@ public class ProfileTest extends ContextTest {
profile.delete("TestProfile");
}
public static String PROFILE_EXAMPLE_FILENAME = "EmptyProfileExample.xml";
public File getResourcesDirectory() throws Exception {
URL logbackFileURL = this.getClass().getClassLoader().getResource("logback-test.xml");
File logbackFile = new File(logbackFileURL.toURI());
File resourcesDirectory = logbackFile.getParentFile();
return resourcesDirectory;
}
public File getProfilesDirectory() throws Exception {
File resourcesDirectory = getResourcesDirectory();
return new File(resourcesDirectory, "profile_examples");
}
public File getSchemaDirectory() throws Exception {
File resourcesDirectory = getResourcesDirectory();
return new File(resourcesDirectory, "profile_schemas");
}
public static String PROFILE_NAME_EXAMPLE = "EmptyProfile";
public static String PROFILE_EXAMPLE_FILENAME = PROFILE_NAME_EXAMPLE + ".xml";
public String fileToString(File file) throws Exception {
try (Stream<String> lines = Files.lines(file.toPath())) {
String content = lines.collect(Collectors.joining(System.lineSeparator()));
return content;
}catch (Exception e) {
throw e;
}
}
@Test
public void testCreateUpdateDeleteGenericResource() throws Exception {
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(PROFILE_EXAMPLE_FILENAME);
String xml = new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
logger.debug("Body\n{}", xml);
File profilesDirectory = getProfilesDirectory();
File profileFile = new File(profilesDirectory, PROFILE_EXAMPLE_FILENAME);
String xml = fileToString(profileFile);
ISProfile profile = new ISProfile();
profile.createOrUpdate(PROFILE_NAME_EXAMPLE, xml);
/*
@ -93,4 +134,37 @@ public class ProfileTest extends ContextTest {
*/
}
protected File getSchemaFile() throws Exception {
File schemaDirectory = getSchemaDirectory();
return new File(schemaDirectory, "profile5.xsd");
}
@Test
public void validateAgainstXSD() throws Exception {
File profilesDirectory = getProfilesDirectory();
File schemaFile = getSchemaFile();
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(schemaFile.toURI().toURL());
Validator validator = schema.newValidator();
for(File profileFile : profilesDirectory.listFiles()) {
String xmlString = fileToString(profileFile);
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse( new InputSource(new StringReader(xmlString)));
DOMSource xml = new DOMSource(doc);
try {
validator.validate(xml);
logger.info("File {} has been successfuly validated against schema.", profileFile.getName());
}catch (Exception e) {
logger.error("Error while validating file {}", profileFile.getName());
throw e;
}
}
}
}

View File

@ -0,0 +1,36 @@
<metadataformat type="DataMiner Process">
<metadatafield categoryref="DataMiner Process">
<fieldName>Input Parameter</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<note>Input parameter expected for the execution of the process</note>
</metadatafield>
<metadatafield categoryref="DataMiner Process">
<fieldName>Output Parameter</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<note>Output parameter expected from the execution of the process </note>
</metadatafield>
<metadatafield categoryref="DataMiner Process">
<fieldName>Process Author</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<maxOccurs>*</maxOccurs>
<defaultValue/>
<note>The name of the author, with email and ORCID. The format should be: family, given[, email][, ORCID]. Example: Smith, John, js@acme.org, orcid.org/0000-0002-1825-0097</note>
<validator>
<regularExpression>^[a-zA-ZÀ-ÿ .'-]+, [a-zA-ZÀ-ÿ .'-]+[,]*([a-zA-Z0-9_!#$%*+=?`{|}~^.-]+@[a-zA-Z0-9À-ÿ.-]+)?[,]*(orcid.org\/0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d\d\d-\d\d\d[\dX])?$</regularExpression>
</validator>
</metadatafield>
<metadatafield categoryref="DataMiner Process">
<fieldName>Process Maintainer</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<maxOccurs>*</maxOccurs>
<defaultValue/>
<note>The name of the author, with email and ORCID. The format should be: family, given[, email][, ORCID]. Example: Smith, John, js@acme.org, orcid.org/0000-0002-1825-0097</note>
<validator>
<regularExpression>^[a-zA-ZÀ-ÿ .'-]+, [a-zA-ZÀ-ÿ .'-]+[,]*([a-zA-Z0-9_!#$%*+=?`{|}~^.-]+@[a-zA-Z0-9À-ÿ.-]+)?[,]*(orcid.org\/0000-000(1-[5-9]|2-[0-9]|3-[0-4])\d\d\d-\d\d\d[\dX])?$</regularExpression>
</validator>
</metadatafield>
</metadataformat>

View File

@ -0,0 +1,10 @@
<metadataformat type="F2DSItem">
<metadatafield>
<fieldName>catalogue_title</fieldName>
<mandatory>true</mandatory>
<dataType>String</dataType>
<defaultValue/>
<note>The catalogue_title the item belongs to.</note>
<grouping create="true">onValue</grouping>
</metadatafield>
</metadataformat>

View File

@ -0,0 +1,36 @@
<metadataformat type="SimpleProfile" version="5">
<metadatafield>
<fieldId>test</fieldId>
<fieldName>My Test</fieldName>
<mandatory>false</mandatory>
<dataType>String</dataType>
<maxOccurs>1</maxOccurs>
<note>Test Field</note>
<tags>
<tag create="true">
<fixedValue>My Tag</fixedValue>
<ifFieldValueMatch>
<regex>^(o|O)(k|K)$</regex>
</ifFieldValueMatch>
</tag>
<tag create="true" separator="-">
<how>onFieldName_onValue</how>
<ifFieldValueMatch>
<regex>^(k|K)(o|O)$</regex>
</ifFieldValueMatch>
</tag>
</tags>
<groups>
<group create="false" propagateUp="true">
<fixedValue>My Group</fixedValue>
<ifFieldValueMatch>
<regex>^true$</regex>
</ifFieldValueMatch>
</group>
</groups>
<extra>
<srcField>myTest</srcField>
<aux>this is just a desc</aux>
</extra>
</metadatafield>
</metadataformat>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="metadataformat">
<xs:complexType>
<xs:sequence>
<xs:element name="metadatafield" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="fieldName" />
<xs:element type="xs:boolean" name="mandatory"
minOccurs="0" maxOccurs="1" />
<xs:element name="dataType">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="String" />
<xs:enumeration value="Time" />
<xs:enumeration value="Time_Interval" />
<xs:enumeration value="Times_ListOf" />
<xs:enumeration value="Text" />
<xs:enumeration value="Boolean" />
<xs:enumeration value="Number" />
<xs:enumeration value="GeoJSON" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element type="xs:string" name="maxOccurs"
minOccurs="0" maxOccurs="1" />
<xs:element type="xs:string" name="defaultValue"
minOccurs="0" maxOccurs="1" />
<xs:element type="xs:string" name="note" minOccurs="0"
maxOccurs="1" />
<xs:element name="vocabulary" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="vocabularyField"
minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute type="xs:boolean" name="isMultiSelection" />
</xs:complexType>
</xs:element>
<xs:element name="validator" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="regularExpression" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="tagging" type="TaggingType"
minOccurs="0" maxOccurs="1">
</xs:element>
<xs:element name="grouping" type="GroupingType"
minOccurs="0" maxOccurs="1">
</xs:element>
</xs:sequence>
<xs:attribute name="categoryref" use="optional" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="NotEmpty" use="required" name="type" />
<xs:attribute name="version" type="xs:integer" use="optional" fixed="3"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="TaggingGroupingValue">
<xs:restriction base="xs:string">
<xs:enumeration value="onFieldName" />
<xs:enumeration value="onValue" />
<xs:enumeration value="onFieldName_onValue" />
<xs:enumeration value="onValue_onFieldName" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TaggingType">
<xs:simpleContent>
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="NotEmpty" name="separator" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="GroupingType">
<xs:simpleContent id="TaggingGroupingValue">
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="xs:boolean" name="propagateUp" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="NotEmpty">
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="metadataformat">
<xs:complexType>
<xs:sequence>
<xs:element name="metadatafield" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="fieldId" minOccurs="0"/>
<xs:element type="xs:string" name="fieldName" />
<xs:element type="xs:boolean" name="mandatory"
minOccurs="0" maxOccurs="1" />
<xs:element name="dataType">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="String" />
<xs:enumeration value="Time" />
<xs:enumeration value="Time_Interval" />
<xs:enumeration value="Times_ListOf" />
<xs:enumeration value="Text" />
<xs:enumeration value="Boolean" />
<xs:enumeration value="Number" />
<xs:enumeration value="GeoJSON" />
<xs:enumeration value="File" />
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element type="xs:string" name="maxOccurs"
minOccurs="0" maxOccurs="1" />
<xs:element type="xs:string" name="defaultValue"
minOccurs="0" maxOccurs="1" />
<xs:element type="xs:string" name="note" minOccurs="0"
maxOccurs="1" />
<xs:element name="vocabulary" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="vocabularyField"
minOccurs="1" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute type="xs:boolean" name="isMultiSelection" />
</xs:complexType>
</xs:element>
<xs:element name="validator" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="regularExpression" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="tagging" type="TaggingType"
minOccurs="0" maxOccurs="1">
</xs:element>
<xs:element name="grouping" type="GroupingType"
minOccurs="0" maxOccurs="1">
</xs:element>
</xs:sequence>
<xs:attribute name="categoryref" use="optional" type="xs:string" />
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="NotEmpty" use="required" name="type" />
<xs:attribute name="version" type="xs:integer" use="optional" fixed="4"/>
</xs:complexType>
</xs:element>
<xs:simpleType name="TaggingGroupingValue">
<xs:restriction base="xs:string">
<xs:enumeration value="onFieldName" />
<xs:enumeration value="onValue" />
<xs:enumeration value="onFieldName_onValue" />
<xs:enumeration value="onValue_onFieldName" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TaggingType">
<xs:simpleContent>
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="NotEmpty" name="separator" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="GroupingType">
<xs:simpleContent id="TaggingGroupingValue">
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="xs:boolean" name="propagateUp" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:simpleType name="NotEmpty">
<xs:restriction base="xs:string">
<xs:minLength value="1" />
</xs:restriction>
</xs:simpleType>
</xs:schema>

View File

@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:vc="http://www.w3.org/2007/XMLSchema-versioning"
vc:minVersion="1.1">
<xs:element name="metadataformat">
<xs:complexType>
<xs:sequence>
<xs:element type="ExtendedMetadataFieldType" name="metadatafield" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute type="NotEmpty" use="required" name="type">
<xs:annotation>
<xs:documentation>
The type (i.e the name) of the profile.
</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="version" type="xs:integer" use="optional" fixed="5">
<xs:annotation>
<xs:documentation>This XSD is valid for gCube Metadata Profile version 5. Any XML conform to this schema must declare such a version as attibute in the root tag.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:complexType name="TagGroupType">
<xs:sequence>
<xs:choice>
<xs:sequence>
<xs:element name="how" minOccurs="1" maxOccurs="1">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="onFieldName"/>
<xs:enumeration value="onValue"/>
<xs:enumeration value="onFieldName_onValue"/>
<xs:enumeration value="onValue_onFieldName"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:sequence>
<xs:element type="NotEmpty" name="fixedValue" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:choice>
<xs:element name="ifFieldValueMatch" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="NotEmpty" name="regex" minOccurs="1" maxOccurs="1"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="create"/>
</xs:complexType>
<xs:complexType name="TagType">
<xs:complexContent>
<xs:extension base="TagGroupType">
<xs:attribute type="NotEmpty" name="separator" default="_"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:complexType name="GroupType">
<xs:complexContent>
<xs:extension base="TagGroupType">
<xs:attribute type="xs:boolean" name="propagateUp" default="false"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:simpleType name="NotEmpty">
<xs:restriction base="xs:string">
<xs:minLength value="1"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="MetadataFieldType">
<xs:sequence>
<xs:element type="xs:string" name="fieldId" minOccurs="0">
<xs:annotation>
<xs:documentation>
It declares (if present in the profile) the value that will be used to specify the field name in the Document (e.g. JSON Document) passed to Service that will store the resulting Document. If the 'fieldId' is absent in the profile, the value of the 'fieldName' (which is mandatory) will be used as field name in the Document.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element type="xs:string" name="fieldName">
<xs:annotation>
<xs:documentation>It contains the name of the metadata field.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element type="xs:boolean" name="mandatory" minOccurs="0"
maxOccurs="1">
<xs:annotation>
<xs:documentation>
It declares if the 'metadatafield' is a field mandatory (by using 'true') or not (by using 'false').
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="dataType">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="String"/>
<xs:enumeration value="Time"/>
<xs:enumeration value="Time_Interval"/>
<xs:enumeration value="Times_ListOf"/>
<xs:enumeration value="Text"/>
<xs:enumeration value="Boolean"/>
<xs:enumeration value="Number"/>
<xs:enumeration value="GeoJSON"/>
<xs:enumeration value="File"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element type="xs:string" name="maxOccurs" minOccurs="0"
maxOccurs="1">
<xs:annotation>
<xs:documentation>
It specifies the maximum number of times that the'metadatafield' can occur: N (as number): if the field must appear N times; * (as char asterisk): if the field can appear an unlimited number of times.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element type="xs:string" name="defaultValue" minOccurs="0"
maxOccurs="1"/>
<xs:element type="xs:string" name="note" minOccurs="0" maxOccurs="1"/>
<xs:element name="vocabulary" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="vocabularyField"
minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute type="xs:boolean" name="isMultiSelection"/>
</xs:complexType>
</xs:element>
<xs:element name="validator" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="regularExpression"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:choice>
<xs:element name="tags" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="TagType" name="tag" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="tagging" type="TaggingType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
This tagging method is deprecated. Please use the tag 'tags' instead.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
<xs:choice>
<xs:element name="groups" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element type="GroupType" name="group" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="grouping" type="GroupingType" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
This grouping method is deprecated. Please use the tag 'groups' instead.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:choice>
</xs:sequence>
<xs:attribute name="categoryref" use="optional" type="xs:string" />
</xs:complexType>
<xs:complexType name="Extra">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" processContents="skip">
<xs:annotation>
<xs:documentation>Any tags are allowed</xs:documentation>
</xs:annotation>
</xs:any>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ExtendedMetadataFieldType">
<xs:complexContent>
<xs:extension base="MetadataFieldType">
<xs:sequence>
<xs:element type="Extra" name="extra" minOccurs="0" maxOccurs="1">
<xs:annotation>
<xs:documentation>
Any 'metadataField' definition can include any additional attibute in this 'extra' tag. This tag and its content are ignored by the validators. They are used by any external tools producing/consuming the profile definition and instances.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<!-- Maintain backward compatibility -->
<xs:simpleType name="TaggingGroupingValue">
<xs:restriction base="xs:string">
<xs:enumeration value="onFieldName" />
<xs:enumeration value="onValue" />
<xs:enumeration value="onFieldName_onValue" />
<xs:enumeration value="onValue_onFieldName" />
</xs:restriction>
</xs:simpleType>
<xs:complexType name="TaggingType">
<xs:simpleContent>
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="NotEmpty" name="separator" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="GroupingType">
<xs:simpleContent id="TaggingGroupingValue">
<xs:extension base="TaggingGroupingValue">
<xs:attribute type="xs:boolean" name="create" />
<xs:attribute type="xs:boolean" name="propagateUp" />
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>