Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WFCORE-7004: use custom parser over default #6206

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public boolean isParseAsElement() {
}

public void parseElement(final AttributeDefinition attribute, final XMLExtendedStreamReader reader, ModelNode operation) throws XMLStreamException {

throw new UnsupportedOperationException();
}

public String getXmlName(final AttributeDefinition attribute){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ private PersistentResourceXMLDescription(PersistentResourceXMLBuilder builder)
LinkedHashMap<String, AttributeDefinition> attrs = new LinkedHashMap<>();
for (AttributeDefinition ad : builder.attributeList) {
attrs.put(ad.getXmlName(), ad);
AttributeParser ap = ad.getParser();
AttributeParser ap = builder.attributeParsers.getOrDefault(ad.getXmlName(), ad.getParser());
if (ap != null && ap.isParseAsElement()) {
attributeElements.put(ap.getXmlName(ad), ad);
}
Expand Down Expand Up @@ -205,7 +205,7 @@ private String parseAttributeGroups(final XMLExtendedStreamReader reader, ModelN
if (element || attributeGroups.contains(localName)) {
if (element) {
AttributeDefinition ad = attributeElements.get(localName);
ad.getParser().parseElement(ad, reader, op);
getAttributeParser(ad).parseElement(ad, reader, op);
final String newLocalName = reader.getLocalName();
if (attributeGroups.contains(newLocalName)) {
parseGroup(reader, op, wildcard);
Expand Down Expand Up @@ -240,7 +240,7 @@ private void parseGroup(XMLExtendedStreamReader reader, ModelNode op, boolean wi
while (reader.hasNext() && reader.nextTag() != END_ELEMENT) {
AttributeDefinition ad = groupAttrs.get(reader.getLocalName());
if (ad != null) {
ad.getParser().parseElement(ad, reader, op);
getAttributeParser(ad).parseElement(ad, reader, op);
} else {
throw ParseUtils.unexpectedElement(reader);
}
Expand All @@ -257,7 +257,7 @@ private String parseAttributes(final XMLExtendedStreamReader reader, ModelNode o
name = value;
} else if (attributes.containsKey(attributeName)) {
AttributeDefinition def = attributes.get(attributeName);
AttributeParser parser = attributeParsers.getOrDefault(attributeName, def.getParser());
AttributeParser parser = getAttributeParser(def);
assert parser != null;
parser.parseAndSetParameter(def, value, op, reader);
} else {
Expand All @@ -273,11 +273,10 @@ private String parseAttributes(final XMLExtendedStreamReader reader, ModelNode o
do {
AttributeDefinition ad = attributeElements.get(reader.getLocalName());
if (ad != null) {
AttributeParser parser = attributeParsers.getOrDefault(ad.getXmlName(), ad.getParser());
parser.parseElement(ad, reader, op);
getAttributeParser(ad).parseElement(ad, reader, op);
} else {
childAlreadyRead = true;
return name; //this means we only have children left, return so child handling logic can take over
return name; //this possibly means we only have children left, return so child handling logic can take over
}
childAlreadyRead = true;
} while (!reader.getLocalName().equals(originalStartElement) && reader.hasNext() && reader.nextTag() != XMLStreamConstants.END_ELEMENT);
Expand Down Expand Up @@ -324,7 +323,7 @@ private void parseChildren(final XMLExtendedStreamReader reader, PathAddress par
if (child != null) {
child.parse(reader, parentAddress, list);
} else if ((elementAd = attributeElements.get(localName)) != null) {
elementAd.getParser().parseElement(elementAd, reader, op);
getAttributeParser(elementAd).parseElement(elementAd, reader, op);
} else if ((child = customChildParsers.get(localName)) != null) {
child.parse(reader, parentAddress, list);
} else {
Expand Down Expand Up @@ -475,14 +474,18 @@ private void persistAttributes(XMLExtendedStreamWriter writer, ModelNode model)
}
}

private AttributeParser getAttributeParser(AttributeDefinition ad) {
return attributeParsers.getOrDefault(ad.getXmlName(), ad.getParser());
}

private void marshallAttributes(XMLExtendedStreamWriter writer, ModelNode model, Collection<AttributeDefinition> attributes, String group) throws XMLStreamException {
boolean started = false;

//we sort attributes to make sure that attributes that marshall to elements are last
List<AttributeDefinition> sortedAds = new ArrayList<>(attributes.size());
List<AttributeDefinition> elementAds = null;
for (AttributeDefinition ad : attributes) {
if (ad.getParser().isParseAsElement()) {
if (getAttributeParser(ad).isParseAsElement()) {
if (elementAds == null) {
elementAds = new ArrayList<>();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.jboss.as.subsystem.test.elementorder;

import org.jboss.as.controller.Extension;
import org.jboss.as.controller.ExtensionContext;
import org.jboss.as.controller.ModelVersion;
import org.jboss.as.controller.PersistentResourceXMLDescriptionWriter;
import org.jboss.as.controller.SubsystemRegistration;
import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
import org.jboss.as.controller.parsing.ExtensionParsingContext;
import org.jboss.as.controller.registry.ManagementResourceRegistration;

import java.util.EnumSet;

public class ElementOrderSubsystemExtension implements Extension {

@Override
public void initialize(ExtensionContext context) {
SubsystemRegistration subsystem = context.registerSubsystem(ElementOrderSubsystemResourceDefinition.SUBSYSTEM_NAME, ModelVersion.create(1));
ManagementResourceRegistration registration = subsystem.registerSubsystemModel(new ElementOrderSubsystemResourceDefinition());
registration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);

subsystem.registerXMLElementWriter(new PersistentResourceXMLDescriptionWriter(ElementOrderSubsystemSchema.VERSION_1_0));
}

@Override
public void initializeParsers(ExtensionParsingContext context) {
context.setSubsystemXmlMappings(ElementOrderSubsystemResourceDefinition.SUBSYSTEM_NAME, EnumSet.of(ElementOrderSubsystemSchema.VERSION_1_0));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.jboss.as.subsystem.test.elementorder;

import org.jboss.as.controller.AttributeDefinition;
import org.jboss.as.controller.PathElement;
import org.jboss.as.controller.ReloadRequiredAddStepHandler;
import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
import org.jboss.as.controller.ResourceRegistration;
import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
import org.jboss.as.controller.SimpleResourceDefinition;
import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
import org.jboss.as.controller.descriptions.NonResolvingResourceDescriptionResolver;
import org.jboss.as.controller.registry.ManagementResourceRegistration;
import org.jboss.dmr.ModelType;

public class ElementOrderSubsystemResourceDefinition extends SimpleResourceDefinition {
static final String SUBSYSTEM_NAME = "element-order";
static final PathElement PATH = PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, SUBSYSTEM_NAME);
static final ResourceRegistration GROUP_REGISTRATION = ResourceRegistration.of(PathElement.pathElement("group"));
static final ResourceRegistration CHILD_REGISTRATION = ResourceRegistration.of(PathElement.pathElement("child"));
static final ResourceRegistration CHILD_2_REGISTRATION = ResourceRegistration.of(PathElement.pathElement("child2"));

static final AttributeDefinition ATTRIBUTE = new SimpleAttributeDefinitionBuilder("attribute", ModelType.STRING)
.setRequired(false)
.build();

static final AttributeDefinition ATTRIBUTE_2 = new SimpleAttributeDefinitionBuilder("attribute2", ModelType.STRING)
.setRequired(false)
.build();

ElementOrderSubsystemResourceDefinition() {
super(new Parameters(PATH, NonResolvingResourceDescriptionResolver.INSTANCE)
.setAddHandler(ReloadRequiredAddStepHandler.INSTANCE)
.setRemoveHandler(ReloadRequiredRemoveStepHandler.INSTANCE));
}

@Override
public void registerChildren(ManagementResourceRegistration registration) {
registration.registerSubModel(new GroupResourceDefinition());
}

public class GroupResourceDefinition extends SimpleResourceDefinition {

GroupResourceDefinition() {
super(new Parameters(GROUP_REGISTRATION, NonResolvingResourceDescriptionResolver.INSTANCE)
.setAddHandler(ReloadRequiredAddStepHandler.INSTANCE)
.setRemoveHandler(ReloadRequiredRemoveStepHandler.INSTANCE));
}

@Override
public void registerAttributes(ManagementResourceRegistration registration) {
registration.registerReadWriteAttribute(ATTRIBUTE, null, ReloadRequiredWriteAttributeHandler.INSTANCE);
registration.registerReadWriteAttribute(ATTRIBUTE_2, null, ReloadRequiredWriteAttributeHandler.INSTANCE);
}

@Override
public void registerChildren(ManagementResourceRegistration registration) {
registration.registerSubModel(new ChildResourceDefinition());
registration.registerSubModel(new Child2ResourceDefinition());
}
}

public class ChildResourceDefinition extends SimpleResourceDefinition {

ChildResourceDefinition() {
super(new Parameters(CHILD_REGISTRATION, NonResolvingResourceDescriptionResolver.INSTANCE)
.setAddHandler(ReloadRequiredAddStepHandler.INSTANCE)
.setRemoveHandler(ReloadRequiredRemoveStepHandler.INSTANCE));
}
}

public class Child2ResourceDefinition extends SimpleResourceDefinition {

Child2ResourceDefinition() {
super(new Parameters(CHILD_2_REGISTRATION, NonResolvingResourceDescriptionResolver.INSTANCE)
.setAddHandler(ReloadRequiredAddStepHandler.INSTANCE)
.setRemoveHandler(ReloadRequiredRemoveStepHandler.INSTANCE));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.jboss.as.subsystem.test.elementorder;

import org.jboss.as.controller.AttributeMarshallers;
import org.jboss.as.controller.AttributeParsers;
import org.jboss.as.controller.PersistentResourceXMLDescription;
import org.jboss.as.controller.PersistentSubsystemSchema;
import org.jboss.as.controller.SubsystemSchema;
import org.jboss.as.controller.xml.VersionedNamespace;
import org.jboss.staxmapper.IntVersion;

public enum ElementOrderSubsystemSchema implements PersistentSubsystemSchema<ElementOrderSubsystemSchema> {
VERSION_1_0;
private final VersionedNamespace<IntVersion, ElementOrderSubsystemSchema> namespace = SubsystemSchema.createSubsystemURN(ElementOrderSubsystemResourceDefinition.SUBSYSTEM_NAME, new IntVersion(1));

@Override
public VersionedNamespace<IntVersion, ElementOrderSubsystemSchema> getNamespace() {
return this.namespace;
}

@Override
public PersistentResourceXMLDescription getXMLDescription() {
PersistentResourceXMLDescription.Factory factory = PersistentResourceXMLDescription.factory(this);
PersistentResourceXMLDescription.Builder builder = factory.builder(ElementOrderSubsystemResourceDefinition.PATH);
PersistentResourceXMLDescription.Builder groupBuilder = factory.builder(ElementOrderSubsystemResourceDefinition.GROUP_REGISTRATION);
groupBuilder.addAttribute(ElementOrderSubsystemResourceDefinition.ATTRIBUTE, AttributeParsers.SIMPLE_ELEMENT, AttributeMarshallers.SIMPLE_ELEMENT);
groupBuilder.addAttribute(ElementOrderSubsystemResourceDefinition.ATTRIBUTE_2, AttributeParsers.SIMPLE_ELEMENT, AttributeMarshallers.SIMPLE_ELEMENT);
groupBuilder.addChild(factory.builder(ElementOrderSubsystemResourceDefinition.CHILD_REGISTRATION).build());
groupBuilder.addChild(factory.builder(ElementOrderSubsystemResourceDefinition.CHILD_2_REGISTRATION).build());
builder.addChild(groupBuilder.build());
return builder.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright The WildFly Authors
* SPDX-License-Identifier: Apache-2.0
*/
package org.jboss.as.subsystem.test.elementorder;

import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;

import javax.xml.stream.XMLStreamException;
import java.io.IOException;

import static org.junit.Assert.fail;

/**
* Test for checking an XML configuration will be correctly parsed when the elements are written in non-default order if the schema allows it
* Default order = attribute elements before children elements
*/
public class ElementOrderSubsystemTestCase extends AbstractSubsystemBaseTest {

public ElementOrderSubsystemTestCase() {
super(ElementOrderSubsystemResourceDefinition.SUBSYSTEM_NAME, new ElementOrderSubsystemExtension());
}

@Override
protected String getSubsystemXml() throws IOException {
return readResource("element-order-1.0.xml");
}

@Override
protected String getSubsystemXsdPath() {
return "schema/wildfly-element-order_1_0.xsd";
}

@Override
protected void compareXml(String configId, String original, String marshalled) {
// do nothing, compareXml imposes the default order
}

@Override
public void testSubsystem() throws Exception {
try {
super.testSubsystem();
} catch (UnsupportedOperationException | XMLStreamException e) {
fail("Parser failed: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<subsystem xmlns="urn:wildfly:element-order:1.0">
<group name="attrs-before-children">
<attribute>abc</attribute>
<attribute2>cdef</attribute2>
<child name="ijk"/>
<child2 name="mnop"/>
</group>
<group name="children-before-attrs">
<child name="abc"/>
<child2 name="cdef"/>
<attribute>ijk</attribute>
<attribute2>mnop</attribute2>
</group>
<group name="mixed">
<child name="abc"/>
<attribute2>cdef</attribute2>
<child2 name="ijk"/>
<attribute>mnop</attribute>
</group>
</subsystem>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:wildfly:element-order:1.0"
xmlns="urn:wildfly:element-order:1.0"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="1.0">

<xs:element name="subsystem" type="subsystem"/>

<xs:complexType name="subsystem">
<xs:sequence maxOccurs="unbounded">
<xs:element name="group" type="group"/>
</xs:sequence>
</xs:complexType>

<xs:complexType name="group">
<xs:all>
<xs:element name="attribute" type="xs:token"/>
<xs:element name="attribute2" type="xs:token"/>
<xs:element name="child" type="child" />
<xs:element name="child2" type="child" />
</xs:all>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>

<xs:complexType name="child">
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
Loading