/* 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 org.fcrepo.server.storage.service;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Vector;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
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.fcrepo.common.Constants;
import org.fcrepo.server.errors.ObjectIntegrityException;
import org.fcrepo.server.errors.RepositoryConfigurationException;
import org.fcrepo.server.storage.types.MethodParmDef;
/**
* A class for parsing the special XML format in Fedora for a Method Map. A
* DSInputSpec exists within a Service Deployment (sDep) and a Service Definition Object (sDef). The Method Map defines abstract methods
* definitions. In a sDef these are the "behavior contract." In a sDep, these
* are abstract definitions that are then implemented by the service represented
* by the sDep.
*
* @author Sandy Payette
*/
class MmapParser
extends DefaultHandler
implements Constants {
/**
* URI-to-namespace prefix mapping info from SAX2 startPrefixMapping events.
*/
private HashMap<String, String> nsPrefixMap;
// Variables for keeping state during SAX parse.
private boolean inMethod = false;
private boolean inUserInputParm = false;
// Fedora Method Map Entities
private Mmap methodMap;
private MmapMethodDef methodMapMethod;
private MmapMethodParmDef methodMapParm;
//private Hashtable wsdlMsgToMethodTbl;
private Hashtable<String, MmapMethodDef> wsdlOperationToMethodDefTbl;
private Hashtable<String, MmapMethodParmDef> wsdlMsgPartToParmDefTbl;
// Working variables...
private Vector<String> tmp_enum;
private Vector<MmapMethodParmDef> tmp_parms;
private Vector<MmapMethodDef> tmp_methods;
/**
* Constructor to enable another class to initiate the parsing
*/
public MmapParser(String parentPID) {
}
/**
* Constructor allows this class to initiate the parsing
*/
public MmapParser(String parentPID, InputStream in)
throws RepositoryConfigurationException, ObjectIntegrityException {
XMLReader xmlReader = null;
try {
SAXParserFactory saxfactory = SAXParserFactory.newInstance();
saxfactory.setValidating(false);
SAXParser parser = saxfactory.newSAXParser();
xmlReader = parser.getXMLReader();
xmlReader.setContentHandler(this);
xmlReader.setFeature("http://xml.org/sax/features/namespaces",
false);
xmlReader
.setFeature("http://xml.org/sax/features/namespace-prefixes",
false);
} catch (Exception e) {
throw new RepositoryConfigurationException("Internal SAX error while "
+ "preparing for Method Map datastream parsing: "
+ e.getMessage());
}
try {
xmlReader.parse(new InputSource(in));
} catch (Exception e) {
throw new ObjectIntegrityException("Error parsing Method Map datastream"
+ e.getClass().getName() + ": " + e.getMessage());
}
}
protected Mmap getMethodMap() {
return methodMap;
}
@Override
public void startDocument() throws SAXException {
nsPrefixMap = new HashMap<String, String>();
wsdlOperationToMethodDefTbl = new Hashtable<String, MmapMethodDef>();
}
@Override
public void endDocument() throws SAXException {
nsPrefixMap = null;
}
@Override
public void startPrefixMapping(String prefix, String uri)
throws SAXException {
nsPrefixMap.put(uri, prefix);
}
@Override
public void skippedEntity(String name) throws SAXException {
char[] text = new char[name.length() + 2];
text[0] = '&';
text[text.length - 1] = ';';
name.getChars(0, name.length(), text, 1);
characters(text, 0, text.length);
}
@Override
public void characters(char ch[], int start, int length)
throws SAXException {
}
@Override
public void startElement(String namespaceURI,
String localName,
String qName,
Attributes attrs) throws SAXException {
if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("MethodMap")) {
methodMap = new Mmap();
methodMap.mmapName = attrs.getValue("name");
tmp_methods = new Vector<MmapMethodDef>();
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("Method")) {
inMethod = true;
methodMapMethod = new MmapMethodDef();
methodMapMethod.methodName = attrs.getValue("operationName");
methodMapMethod.methodLabel = "fix me";
methodMapMethod.wsdlOperationName = attrs.getValue("operationName");
methodMapMethod.wsdlMessageName = attrs.getValue("wsdlMsgName");
methodMapMethod.wsdlOutputMessageName =
attrs.getValue("wsdlMsgOutput");
tmp_parms = new Vector<MmapMethodParmDef>();
wsdlMsgPartToParmDefTbl = new Hashtable<String, MmapMethodParmDef>();
} else if (inMethod) {
if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("DatastreamInputParm")) {
methodMapParm = new MmapMethodParmDef();
methodMapParm.wsdlMessagePartName = attrs.getValue("parmName");
methodMapParm.parmName = attrs.getValue("parmName");
methodMapParm.parmLabel = "fix me";
methodMapParm.parmPassBy = attrs.getValue("passBy");
methodMapParm.parmType = MethodParmDef.DATASTREAM_INPUT;
if (attrs.getValue("required") == null) {
methodMapParm.parmRequired = true;
} else {
methodMapParm.parmRequired =
Boolean.parseBoolean(attrs.getValue("required"));
}
methodMapParm.parmDefaultValue = null;
methodMapParm.parmDomainValues = EMPTY_STRING_ARRAY;
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("DefaultInputParm")) {
methodMapParm = new MmapMethodParmDef();
methodMapParm.wsdlMessagePartName = attrs.getValue("parmName");
methodMapParm.parmName = attrs.getValue("parmName");
methodMapParm.parmLabel = "fix me";
methodMapParm.parmPassBy = MethodParmDef.PASS_BY_VALUE;
methodMapParm.parmType = MethodParmDef.DEFAULT_INPUT;
if (attrs.getValue("required") == null) {
methodMapParm.parmRequired = true;
} else {
methodMapParm.parmRequired =
Boolean.parseBoolean(attrs.getValue("required"));
}
methodMapParm.parmDefaultValue = attrs.getValue("defaultValue");
methodMapParm.parmDomainValues = EMPTY_STRING_ARRAY;
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("UserInputParm")) {
inUserInputParm = true;
methodMapParm = new MmapMethodParmDef();
methodMapParm.wsdlMessagePartName = attrs.getValue("parmName");
methodMapParm.parmName = attrs.getValue("parmName");
methodMapParm.parmLabel = "fix me";
methodMapParm.parmPassBy = MethodParmDef.PASS_BY_VALUE;
methodMapParm.parmType = MethodParmDef.USER_INPUT;
if (attrs.getValue("required") == null) {
methodMapParm.parmRequired = true;
} else {
methodMapParm.parmRequired =
Boolean.parseBoolean(attrs.getValue("required"));
}
methodMapParm.parmDefaultValue = attrs.getValue("defaultValue");
} else if (inUserInputParm) {
if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("ValidParmValues")) {
tmp_enum = new Vector<String>();
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("ValidParm")) {
tmp_enum.add(attrs.getValue("value"));
}
}
}
}
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("MethodMap")) {
methodMap.mmapMethods =
(MmapMethodDef[]) tmp_methods.toArray(new MmapMethodDef[0]);
methodMap.wsdlOperationToMethodDef = wsdlOperationToMethodDefTbl;
tmp_methods = null;
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("Method")) {
methodMapMethod.methodParms =
(MethodParmDef[]) tmp_parms.toArray(new MethodParmDef[0]);
methodMapMethod.wsdlMsgParts =
(MmapMethodParmDef[]) tmp_parms
.toArray(new MmapMethodParmDef[0]);
methodMapMethod.wsdlMsgPartToParmDefTbl = wsdlMsgPartToParmDefTbl;
tmp_methods.add(methodMapMethod);
wsdlOperationToMethodDefTbl.put(methodMapMethod.methodName,
methodMapMethod);
wsdlMsgPartToParmDefTbl = null;
methodMapMethod = null;
tmp_parms = null;
inMethod = false;
} else if (inMethod) {
if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("DatastreamInputParm")) {
tmp_parms.add(methodMapParm);
wsdlMsgPartToParmDefTbl.put(methodMapParm.wsdlMessagePartName,
methodMapParm);
methodMapParm = null;
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("DefaultInputParm")) {
tmp_parms.add(methodMapParm);
wsdlMsgPartToParmDefTbl.put(methodMapParm.wsdlMessagePartName,
methodMapParm);
methodMapParm = null;
} else if (namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("UserInputParm")) {
tmp_parms.add(methodMapParm);
wsdlMsgPartToParmDefTbl.put(methodMapParm.wsdlMessagePartName,
methodMapParm);
methodMapParm = null;
inUserInputParm = false;
} else if (inUserInputParm
&& namespaceURI.equalsIgnoreCase(METHOD_MAP.uri)
&& localName.equalsIgnoreCase("ValidParmValues")) {
methodMapParm.parmDomainValues =
(String[]) tmp_enum.toArray(EMPTY_STRING_ARRAY);
tmp_enum = null;
}
}
}
}