diff --git a/modello-core/src/main/java/org/codehaus/modello/ModelloParameterConstants.java b/modello-core/src/main/java/org/codehaus/modello/ModelloParameterConstants.java index c69a434f1..9e9db422b 100644 --- a/modello-core/src/main/java/org/codehaus/modello/ModelloParameterConstants.java +++ b/modello-core/src/main/java/org/codehaus/modello/ModelloParameterConstants.java @@ -71,6 +71,13 @@ public class ModelloParameterConstants */ public static final String EXTENDED_CLASSNAME_SUFFIX = "modello.xpp3.extended.suffix"; + /** + * Boolean flag enforcing existence of mandatory elements in the XSD. + * If set to {@code false} will not require mandatory elements in the XML which can be useful if the XML is post processed (e.g. POM merging with parents) + * where mandatory elements might be contributed by sources outside the XML. + * @since 2.1 + */ + public static final String XSD_ENFORCE_MANDATORY_ELEMENTS = "modello.xsd.enforce.mandatory.element"; private ModelloParameterConstants() { } diff --git a/modello-maven-plugin/src/main/java/org/codehaus/modello/maven/ModelloXsdMojo.java b/modello-maven-plugin/src/main/java/org/codehaus/modello/maven/ModelloXsdMojo.java index c0b55fcc2..161789df0 100644 --- a/modello-maven-plugin/src/main/java/org/codehaus/modello/maven/ModelloXsdMojo.java +++ b/modello-maven-plugin/src/main/java/org/codehaus/modello/maven/ModelloXsdMojo.java @@ -45,6 +45,15 @@ public class ModelloXsdMojo @Parameter( defaultValue = "${project.build.directory}/generated-site/resources/xsd", required = true ) private File outputDirectory; + /** + * Boolean flag to enforce mandatory elements in the XML schema. + * If set to {@code false} the XSD won't enforce mandatory elements in the XML which can be useful if the XML is post processed (e.g. POM merging with parents). + * The default value is {@code false} for backwards compatibility reasons, but should be set to {@code true} for most cases. + * @since 2.1.0 + */ + @Parameter( defaultValue = "false") + private boolean enforceMandatoryElements; + /** * * @since 1.0-alpha-21 @@ -65,6 +74,7 @@ protected void customizeParameters( Properties parameters ) { parameters.put( ModelloParameterConstants.OUTPUT_XSD_FILE_NAME, xsdFileName ); } + parameters.put( ModelloParameterConstants.XSD_ENFORCE_MANDATORY_ELEMENTS, enforceMandatoryElements ); } protected boolean producesCompilableResult() diff --git a/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java b/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java index 7a2c72e4a..e3cec9459 100644 --- a/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java +++ b/modello-plugins/modello-plugin-xsd/src/main/java/org/codehaus/modello/plugin/xsd/XsdGenerator.java @@ -87,6 +87,7 @@ private void generateXsd( Properties parameters ) // we assume parameters not null String xsdFileName = parameters.getProperty( ModelloParameterConstants.OUTPUT_XSD_FILE_NAME ); + boolean enforceMandatoryElements = Boolean.parseBoolean( parameters.getProperty( ModelloParameterConstants.XSD_ENFORCE_MANDATORY_ELEMENTS ) ); File f = new File( directory, objectModel.getId() + "-" + getGeneratedVersion() + ".xsd" ); @@ -137,7 +138,8 @@ private void generateXsd( Properties parameters ) // Element descriptors // Traverse from root so "abstract" models aren't included int initialCapacity = objectModel.getClasses( getGeneratedVersion() ).size(); - writeComplexTypeDescriptor( w, objectModel, root, new HashSet( initialCapacity ) ); + writeComplexTypeDescriptor( w, objectModel, root, new HashSet( initialCapacity ), + enforceMandatoryElements ); w.endElement(); } @@ -184,7 +186,7 @@ private static void writeDocumentation( XMLWriter w, String version, String desc } private void writeComplexTypeDescriptor( XMLWriter w, Model objectModel, ModelClass modelClass, - Set written ) + Set written, boolean enforceMandatoryElements ) { written.add( modelClass ); @@ -242,9 +244,12 @@ private void writeComplexTypeDescriptor( XMLWriter w, Model objectModel, ModelCl { w.startElement( "xs:element" ); - // Usually, would only do this if the field is not "required", but due to inheritance, it may be - // present, even if not here, so we need to let it slide - w.addAttribute( "minOccurs", "0" ); + if ( !enforceMandatoryElements || !field.isRequired() ) + { + // Usually, would only do this if the field is not "required", but due to inheritance, it may be + // present, even if not here, so we need to let it slide + w.addAttribute( "minOccurs", "0" ); + } } String xsdType = getXsdType( field.getType() ); @@ -428,7 +433,7 @@ else if ( xsdType == null ) { if ( !written.contains( fieldModelClass ) ) { - writeComplexTypeDescriptor( w, objectModel, fieldModelClass, written ); + writeComplexTypeDescriptor( w, objectModel, fieldModelClass, written, enforceMandatoryElements ); } } } diff --git a/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/FeaturesXsdGeneratorTest.java b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/FeaturesXsdGeneratorTest.java index dce140aff..30c612a0b 100644 --- a/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/FeaturesXsdGeneratorTest.java +++ b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/FeaturesXsdGeneratorTest.java @@ -24,6 +24,7 @@ import org.codehaus.modello.AbstractModelloGeneratorTest; import org.codehaus.modello.ModelloException; +import org.codehaus.modello.ModelloParameterConstants; import org.codehaus.modello.core.ModelloCore; import org.codehaus.modello.model.Model; import org.xml.sax.SAXParseException; @@ -56,7 +57,8 @@ public void testXsdGenerator() Model model = modello.loadModel( getXmlResourceReader( "/features.mdo" ) ); Properties parameters = getModelloParameters( "1.0.0" ); - + parameters.setProperty( ModelloParameterConstants.XSD_ENFORCE_MANDATORY_ELEMENTS, "true" ); + modello.generate( model, "xsd", parameters ); SchemaFactory sf = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI ); @@ -80,7 +82,19 @@ public void testXsdGenerator() catch ( SAXParseException e ) { // ok, expected exception - assertTrue( String.valueOf( e.getMessage() ).contains( "invalidElement" ) ); + assertTrue( e.getMessage().contains( "invalidElement" ) ); + } + + try + { + validator.validate( new StreamSource( getClass().getResourceAsStream( "/features-missing-required.xml" ) ) ); + fail( "parsing of features-invalid.xml should have failed" ); + } + catch ( SAXParseException e ) + { + // ok, expected exception + assertTrue( e.getMessage().contains( "description" ) ); + assertTrue( e.getMessage().endsWith(" is expected.")); } try @@ -91,7 +105,7 @@ public void testXsdGenerator() catch ( SAXParseException e ) { // ok, expected exception - assertTrue( String.valueOf( e.getMessage() ).contains( "transientString" ) ); + assertTrue( e.getMessage().contains( "transientString" ) ); } } } diff --git a/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/ModelloXsdGeneratorTest.java b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/ModelloXsdGeneratorTest.java index 1aa4440b7..2729c0b63 100644 --- a/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/ModelloXsdGeneratorTest.java +++ b/modello-plugins/modello-plugin-xsd/src/test/java/org/codehaus/modello/plugin/xsd/ModelloXsdGeneratorTest.java @@ -23,6 +23,7 @@ */ import org.codehaus.modello.AbstractModelloGeneratorTest; +import org.codehaus.modello.ModelloParameterConstants; import org.codehaus.modello.core.ModelloCore; import org.codehaus.modello.model.Model; import org.xml.sax.SAXException; diff --git a/modello-plugins/modello-plugin-xsd/src/test/resources/features-missing-required.xml b/modello-plugins/modello-plugin-xsd/src/test/resources/features-missing-required.xml new file mode 100644 index 000000000..5117918ac --- /dev/null +++ b/modello-plugins/modello-plugin-xsd/src/test/resources/features-missing-required.xml @@ -0,0 +1,5 @@ + + + + diff --git a/modello-test/src/main/resources/features.xml b/modello-test/src/main/resources/features.xml index 6f0c20cd0..079a167fb 100644 --- a/modello-test/src/main/resources/features.xml +++ b/modello-test/src/main/resources/features.xml @@ -3,7 +3,7 @@ 1.0.0 - + id reference