/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.client.objecteditor.types;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Turns a datastream input spec into a java object(s).
*/
class DatastreamInputSpecDeserializer
extends DefaultHandler {
/** The deserialized input spec */
private DatastreamInputSpec m_result;
// values gathered and built while parsing
private String m_label;
private List m_bindingRules;
private String m_min;
private String m_max;
private String m_orderMatters;
private String m_key;
private StringBuffer m_inputLabel;
private StringBuffer m_inputInstruction;
private StringBuffer m_types;
// for character content, which element are we reading?
private int m_readingContent;
private static int NONE = 0;
private static int INPUT_LABEL = 1;
private static int TYPES = 2;
private static int INPUT_INSTRUCTION = 3;
public DatastreamInputSpecDeserializer(InputStream xml)
throws IOException {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
SAXParser parser = spf.newSAXParser();
parser.parse(xml, this);
} catch (Exception e) {
if (e.getMessage() != null) {
throw new IOException(e.getMessage());
} else {
throw new IOException("Error parsing datastream input spec: "
+ e.getClass().getName());
}
}
}
public DatastreamInputSpec getResult() {
return m_result;
}
@Override
public void startElement(String uri,
String localName,
String qName,
Attributes a) {
if (localName.equals("DSInputSpec")) {
m_bindingRules = new ArrayList();
for (int i = 0; i < a.getLength(); i++) {
String name = a.getLocalName(i);
if (name.equals("label")) {
m_label = a.getValue(i);
}
}
} else if (localName.equals("DSInput")) {
m_inputLabel = new StringBuffer();
m_inputInstruction = new StringBuffer();
m_types = new StringBuffer();
for (int i = 0; i < a.getLength(); i++) {
String name = a.getLocalName(i);
if (name.equals("DSMin")) {
m_min = a.getValue(i);
} else if (name.equals("DSMax")) {
m_max = a.getValue(i);
} else if (name.equals("DSOrdinality")) {
m_orderMatters = a.getValue(i);
} else if (name.equals("wsdlMsgPartName")) {
m_key = a.getValue(i);
}
}
} else if (localName.equals("DSInputLabel")) {
m_readingContent = INPUT_LABEL;
} else if (localName.equals("DSMIME")) {
m_readingContent = TYPES;
} else if (localName.equals("DSInputInstruction")) {
m_readingContent = INPUT_INSTRUCTION;
}
}
@Override
public void characters(char[] ch, int start, int length) {
if (m_readingContent == INPUT_LABEL) {
m_inputLabel.append(ch, start, length);
} else if (m_readingContent == TYPES) {
m_types.append(ch, start, length);
} else if (m_readingContent == INPUT_INSTRUCTION) {
m_inputInstruction.append(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equals("DSInputLabel") || localName.equals("DSMIME")
|| localName.equals("DSInputInstruction")) {
m_readingContent = NONE;
if (localName.equals("DSMIME")) {
// there might be multiple elements, so add a space,
// which can't hurt since later it's trimmed
m_types.append(" ");
}
} else if (localName.equals("DSInput")) {
// first interpret what we read,
// converting to appropriate types and defualt values
int min;
try {
min = Integer.parseInt(m_min);
} catch (Exception e) {
min = 1; // default the same way xsd:minOccurs does
}
int max;
try {
max = Integer.parseInt(m_max);
} catch (Exception e) {
if (m_max != null
&& (m_max.startsWith("-") || m_max.startsWith("n")
|| m_max.startsWith("N")
|| m_max.startsWith("u")
|| m_max.startsWith("U")
|| m_max.startsWith("i") || m_max
.startsWith("I"))) {
// covers various spellings of "n/a", "none", "unbounded",
// "unrestricted", "infinite", and -1
max = -1;
} else {
max = 1; // default the same way xsd:maxOccurs does
}
}
boolean orderMatters = false;
if (m_orderMatters != null
&& (m_orderMatters.startsWith("y")
|| m_orderMatters.startsWith("Y")
|| m_orderMatters.startsWith("t")
|| m_orderMatters.startsWith("T") || m_orderMatters
.equals("1"))) {
// covers various spellings of "yes", "true", and 1
orderMatters = true;
}
String[] types =
m_types.toString().replaceAll(" +", " ").trim().split(" ");
// then add it to the list of rules
m_bindingRules.add(new DatastreamBindingRule(m_key,
m_inputLabel
.toString(),
m_inputInstruction
.toString(),
min,
max,
orderMatters,
types));
} else if (localName.equals("DSInputSpec")) {
m_result = new DatastreamInputSpec(m_label, m_bindingRules);
}
}
}