/*
* JBoss, Home of Professional Open Source.
* Copyright 2015, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.wildfly.extension.clustering.singleton;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import org.jboss.as.clustering.controller.Attribute;
import org.jboss.as.controller.PathAddress;
import org.jboss.as.controller.operations.common.Util;
import org.jboss.as.controller.parsing.ParseUtils;
import org.jboss.dmr.ModelNode;
import org.jboss.staxmapper.XMLElementReader;
import org.jboss.staxmapper.XMLExtendedStreamReader;
/**
* Parses singleton deployer subsystem configuration from XML.
* @author Paul Ferraro
*/
public class SingletonXMLReader implements XMLElementReader<List<ModelNode>> {
@SuppressWarnings("unused")
private final SingletonSchema schema;
public SingletonXMLReader(SingletonSchema schema) {
this.schema = schema;
}
@Override
public void readElement(XMLExtendedStreamReader reader, List<ModelNode> result) throws XMLStreamException {
Map<PathAddress, ModelNode> operations = new LinkedHashMap<>();
PathAddress address = PathAddress.pathAddress(SingletonResourceDefinition.PATH);
ModelNode operation = Util.createAddOperation(address);
operations.put(address, operation);
while (reader.hasNext() && reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
XMLElement element = XMLElement.forName(reader);
switch (element) {
case SINGLETON_POLICIES: {
this.parseSingletonPolicies(reader, address, operations);
break;
}
default : {
throw ParseUtils.unexpectedElement(reader);
}
}
}
result.addAll(operations.values());
}
private void parseSingletonPolicies(XMLExtendedStreamReader reader, PathAddress address, Map<PathAddress, ModelNode> operations) throws XMLStreamException {
ModelNode operation = operations.get(address);
for (int i = 0; i < reader.getAttributeCount(); ++i) {
XMLAttribute attribute = XMLAttribute.forName(reader, i);
switch (attribute) {
case DEFAULT: {
readAttribute(reader, i, operation, SingletonResourceDefinition.Attribute.DEFAULT);
break;
}
default: {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
}
while (reader.hasNext() && reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
XMLElement element = XMLElement.forName(reader);
switch (element) {
case SINGLETON_POLICY: {
this.parseSingletonPolicy(reader, address, operations);
break;
}
default : {
throw ParseUtils.unexpectedElement(reader);
}
}
}
}
private void parseSingletonPolicy(XMLExtendedStreamReader reader, PathAddress subsystemAddress, Map<PathAddress, ModelNode> operations) throws XMLStreamException {
String name = XMLAttribute.NAME.require(reader);
PathAddress address = subsystemAddress.append(SingletonPolicyResourceDefinition.pathElement(name));
ModelNode operation = Util.createAddOperation(address);
operations.put(address, operation);
for (int i = 0; i < reader.getAttributeCount(); ++i) {
XMLAttribute attribute = XMLAttribute.forName(reader, i);
switch (attribute) {
case NAME: {
// Already parsed
break;
}
case CACHE_CONTAINER: {
readAttribute(reader, i, operation, SingletonPolicyResourceDefinition.Attribute.CACHE_CONTAINER);
break;
}
case CACHE: {
readAttribute(reader, i, operation, SingletonPolicyResourceDefinition.Attribute.CACHE);
break;
}
case QUORUM: {
readAttribute(reader, i, operation, SingletonPolicyResourceDefinition.Attribute.QUORUM);
break;
}
default: {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
}
while (reader.hasNext() && reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
XMLElement element = XMLElement.forName(reader);
switch (element) {
case RANDOM_ELECTION_POLICY: {
this.parseRandomElectionPolicy(reader, address, operations);
break;
}
case SIMPLE_ELECTION_POLICY: {
this.parseSimpleElectionPolicy(reader, address, operations);
break;
}
default : {
throw ParseUtils.unexpectedElement(reader);
}
}
}
}
private void parseRandomElectionPolicy(XMLExtendedStreamReader reader, PathAddress policyAddress, Map<PathAddress, ModelNode> operations) throws XMLStreamException {
PathAddress address = policyAddress.append(RandomElectionPolicyResourceDefinition.PATH);
ModelNode operation = Util.createAddOperation(address);
operations.put(address, operation);
ParseUtils.requireNoAttributes(reader);
this.parsePreferences(reader, operation);
}
private void parseSimpleElectionPolicy(XMLExtendedStreamReader reader, PathAddress policyAddress, Map<PathAddress, ModelNode> operations) throws XMLStreamException {
PathAddress address = policyAddress.append(SimpleElectionPolicyResourceDefinition.PATH);
ModelNode operation = Util.createAddOperation(address);
operations.put(address, operation);
for (int i = 0; i < reader.getAttributeCount(); ++i) {
XMLAttribute attribute = XMLAttribute.forName(reader, i);
switch (attribute) {
case POSITION: {
readAttribute(reader, i, operation, SimpleElectionPolicyResourceDefinition.Attribute.POSITION);
break;
}
default: {
throw ParseUtils.unexpectedAttribute(reader, i);
}
}
}
this.parsePreferences(reader, operation);
}
@SuppressWarnings("static-method")
private void parsePreferences(XMLExtendedStreamReader reader, ModelNode operation) throws XMLStreamException {
while (reader.hasNext() && reader.nextTag() != XMLStreamConstants.END_ELEMENT) {
XMLElement element = XMLElement.forName(reader);
switch (element) {
case NAME_PREFERENCES: {
readElement(reader, operation, ElectionPolicyResourceDefinition.Attribute.NAME_PREFERENCES);
break;
}
case SOCKET_BINDING_PREFERENCES: {
readElement(reader, operation, ElectionPolicyResourceDefinition.Attribute.SOCKET_BINDING_PREFERENCES);
break;
}
default : {
throw ParseUtils.unexpectedElement(reader);
}
}
}
}
private static void readAttribute(XMLExtendedStreamReader reader, int index, ModelNode operation, Attribute attribute) throws XMLStreamException {
attribute.getDefinition().getParser().parseAndSetParameter(attribute.getDefinition(), reader.getAttributeValue(index), operation, reader);
}
private static void readElement(XMLExtendedStreamReader reader, ModelNode operation, Attribute attribute) throws XMLStreamException {
attribute.getDefinition().getParser().parseAndSetParameter(attribute.getDefinition(), reader.getElementText(), operation, reader);
}
}