blob: 0ca6127f14e93617e1021cb7b3f9844a756fd049 [file] [log] [blame]
/*
* Copyright 2009-2010 by The Regents of the University of California
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* you may obtain a copy of the License from
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.uci.ics.hyracks.api.topology;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import edu.uci.ics.hyracks.api.topology.NetworkEndpoint.EndpointType;
public class TopologyDefinitionParser {
private final Stack<ElementStackEntry> stack;
private boolean inPropertyElement;
private TopologyDefinitionParser() {
stack = new Stack<ElementStackEntry>();
inPropertyElement = false;
}
public static ClusterTopology parse(InputSource in) throws IOException, SAXException {
TopologyDefinitionParser parser = new TopologyDefinitionParser();
return parser.parseInternal(in);
}
private ClusterTopology parseInternal(InputSource in) throws IOException, SAXException {
XMLReader parser;
parser = XMLReaderFactory.createXMLReader();
SAXContentHandler handler = new SAXContentHandler();
parser.setContentHandler(handler);
parser.parse(in);
if (stack.size() != 1) {
throw new IllegalStateException("Malformed topology definition");
}
ElementStackEntry e = stack.pop();
if (e.ports.size() != 1) {
throw new IllegalArgumentException("Malformed topology definition");
}
NetworkEndpoint endpoint = e.ports.get(0).getEndpoint();
if (endpoint.getType() != EndpointType.NETWORK_SWITCH) {
throw new IllegalArgumentException("Top level content in cluster-topology must be network-switch");
}
return new ClusterTopology((NetworkSwitch) endpoint);
}
private class SAXContentHandler extends DefaultHandler {
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("network-switch".equals(localName) || "terminal".equals(localName)) {
ElementStackEntry e = stack.pop();
NetworkEndpoint endpoint = e.type == EndpointType.NETWORK_SWITCH ? new NetworkSwitch(e.name,
e.properties, e.ports.toArray(new NetworkSwitch.Port[e.ports.size()])) : new NetworkTerminal(
e.name, e.properties);
stack.peek().ports.add(new NetworkSwitch.Port(endpoint));
} else if ("property".equals(localName)) {
if (!inPropertyElement) {
throw new IllegalStateException("Improperly nested property element encountered");
}
inPropertyElement = false;
}
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if ("cluster-topology".equals(localName)) {
if (!stack.isEmpty()) {
throw new IllegalStateException("Encountered unexpected " + qName);
}
stack.push(new ElementStackEntry(null, ""));
} else if ("network-switch".equals(localName) || "terminal".equals(localName)) {
String name = atts.getValue("", "name");
if (name == null) {
throw new IllegalStateException("Encountered " + localName + " element with no name attribute");
}
EndpointType type = "network-switch".equals(localName) ? EndpointType.NETWORK_SWITCH
: EndpointType.NETWORK_TERMINAL;
ElementStackEntry e = new ElementStackEntry(type, name);
stack.push(e);
} else if ("property".equals(localName)) {
if (inPropertyElement) {
throw new IllegalStateException("Improperly nested property element encountered");
}
String name = atts.getValue("", "name");
if (name == null) {
throw new IllegalStateException("Encountered " + localName + " element with no name attribute");
}
String value = atts.getValue("", "value");
if (value == null) {
throw new IllegalStateException("Encountered " + localName + " element with no value attribute");
}
stack.peek().properties.put(name, value);
inPropertyElement = true;
}
}
}
private static class ElementStackEntry {
private final EndpointType type;
private final String name;
private final Map<String, String> properties;
private final List<NetworkSwitch.Port> ports;
public ElementStackEntry(EndpointType type, String name) {
this.type = type;
this.name = name;
this.properties = new HashMap<String, String>();
ports = new ArrayList<NetworkSwitch.Port>();
}
}
}