package edu.neu.ccs.task.util;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import webframe.Resource;
import com.thaiopensource.datatype.xsd.DatatypeLibraryFactoryImpl;
import com.thaiopensource.util.PropertyMapBuilder;
import com.thaiopensource.validate.ValidationDriver;
import com.thaiopensource.validate.rng.CompactSchemaReader;
import com.thaiopensource.validate.rng.RngProperty;
import edu.neu.ccs.task.TaskModelSet;
/**
* Miscellaneous XML-related utilities.
*
* @author Dan Schulman
* @version $Id: XMLUtil.java 731 2009-10-12 19:53:20Z schulman $
*/
public class XMLUtil {
private XMLUtil() {}
/**
* Skip forward until we find a particular kind of item.
*
* @param xml an xml stream
* @param type from XMLStreamConstants
* @throws XMLStreamException if the end of the document is reached
*/
public static void skipTo(XMLStreamReader xml, int type)
throws XMLStreamException {
while (xml.hasNext())
if (xml.next() == type)
return;
throw new XMLStreamException();
}
/**
* Parse a string (which may or may not have a prefix) into a qualified
* name. Use the task engine's prefix-to-URI mapping to resolve
* prefixes.
*
* @param engine a task engine
* @param name the name string
* @return a qualified name
*/
public static QName parseQName(TaskModelSet modelSet, String name) {
String[] parts = name.split(":", 2);
if (parts.length == 1)
return new QName(modelSet.getDefaultModel().getURI(), name); // no prefix
return new QName(modelSet.getModelForPrefix(parts[0]).getURI(), parts[1], parts[0]);
}
public static boolean isURI(String fileOrURI) {
try {
URI uri = new URI(fileOrURI);
if (uri.getScheme() != null)
return true;
} catch (URISyntaxException e) {
}
return false;
}
/*public static String toURI(String fileOrURI) {
if (isURI(fileOrURI))
return fileOrURI;
return new File(fileOrURI).getAbsoluteFile().toURI().toString();
}*/
/**
* Validate an XML document against a RELAX NG schema.
*
* @param s the document location (a file or URL)
* @param schema the schmea location
* @return true if validated
* @throws IOException
*/
public static boolean validate(String s, URL schema)
throws IOException {
InputSource in;
InputStream is = null;
if (isURI(s))
in = new InputSource(s);
else {
is = new FileInputStream(s);
in = new InputSource(is);
in.setSystemId(s);
}
try {
return validate(in, schema);
} finally {
if (is != null) is.close();
}
}
public static boolean validate(Resource r, URL schema)
throws IOException {
InputStream in = r.open();
try {
InputSource source = new InputSource(in);
source.setSystemId(r.location());
return validate(source, schema);
} finally {
in.close();
}
}
public static boolean validate(InputSource in, URL schema)
throws IOException {
// explicit datatype factory is workaround for Jing bug wrt to OS X
PropertyMapBuilder properties = new PropertyMapBuilder();
RngProperty.DATATYPE_LIBRARY_FACTORY.put(properties,
new DatatypeLibraryFactoryImpl());
ValidationDriver driver = new ValidationDriver(
properties.toPropertyMap(),
CompactSchemaReader.getInstance());
InputStream schemaIn = schema.openStream();
try {
InputSource schemaSource = new InputSource(schema.openStream());
schemaSource.setSystemId(schema.toString());
driver.loadSchema(schemaSource);
return driver.validate(in);
} catch (SAXException e) {
System.out.println(e);
return false;
} finally {
schemaIn.close();
}
}
/**
* @return the location of the CEA-2018 RELAX NG schema
*/
public static URL getBaseSchema() {
return XMLUtil.class.getResource(
"/edu/neu/ccs/task/schema/cea-2018.rnc");
}
/**
* @return the location of the CEA-2018+DTask RELAX NG schema
*/
public static URL getDialogueSchema() {
return XMLUtil.class.getResource(
"/edu/neu/ccs/task/schema/cea-2018-dialogue.rnc");
}
}