/*
* XMLResponseParser.java
*
* Created on May 22, 2007, 10:02 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.app.client;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.ElementEnd;
import org.infoset.xml.Item;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.Name;
import org.infoset.xml.Validity;
import org.infoset.xml.XMLException;
import org.infoset.xml.filter.ItemFilter;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.infoset.xml.util.DocumentDestination;
import org.infoset.xml.xerces.XMLSchemaValidationFilter;
import org.restlet.Response;
import org.restlet.data.MediaType;
import org.restlet.representation.Representation;
/**
*
* @author alex
*/
public class XMLRepresentationParser
{
DocumentLoader loader = new SAXDocumentLoader();
boolean validate;
Map<URI,URL> schemaMap;
List<Name> topLevelElements;
/** Creates a new instance of XMLResponseParser */
public XMLRepresentationParser()
{
schemaMap = null;
validate = false;
topLevelElements = null;
}
public boolean isValidating() {
return validate;
}
public void setValidation(boolean flag)
{
validate = flag;
}
public void addNamespaceLocation(URI namespace,URL location) {
if (schemaMap==null) {
schemaMap = new TreeMap<URI,URL>();
}
schemaMap.put(namespace,location);
}
public void setSchemaMap(Map<URI,URL> map)
{
schemaMap = map;
}
public Map<URI,URL> getSchemaMap() {
return schemaMap;
}
public List<Name> getAllowedElements() {
return topLevelElements;
}
public void setAllowedElements(List<Name> list) {
topLevelElements = list;
}
public void addAllowedElement(Name name)
{
if (topLevelElements==null) {
topLevelElements = new ArrayList<Name>();
}
topLevelElements.add(name);
}
protected ItemFilter createValidationFilter(ItemDestination end)
throws XMLException
{
final XMLSchemaValidationFilter validate = new XMLSchemaValidationFilter();
if (schemaMap!=null) {
for (URI namespace : schemaMap.keySet()) {
validate.addNamespaceMap(namespace,schemaMap.get(namespace));
}
}
ItemFilter checkValidity = new ItemFilter() {
ItemDestination output;
int level = -1;
public void send(Item item)
throws XMLException
{
switch (item.getType()) {
case DocumentItem:
level = -1;
break;
case ElementItem:
level++;
break;
case ElementEndItem:
level--;
ElementEnd end = (ElementEnd)item;
if (level<0) {
if (end.getValidity()!=Validity.VALID) {
StringBuilder builder = new StringBuilder();
Iterator errors = validate.getErrors();
while (errors.hasNext()) {
builder.append("\n");
builder.append(errors.next().toString());
}
throw new XMLException("Element "+end.getName()+" is not valid:"+builder.toString());
}
if (topLevelElements!=null) {
Name name = end.getName();
if (!topLevelElements.contains(name)) {
throw new XMLException("Unexpected document element "+name);
}
}
}
break;
}
output.send(item);
}
public void attach(ItemDestination output) {
this.output = output;
}
};
validate.attach(checkValidity);
checkValidity.attach(end);
return validate;
}
public void parse(Response response, ItemDestination dest)
throws IOException,XMLException
{
parse(response.getEntity(),URI.create(response.getRequest().getResourceRef().toString()),dest);
}
public void parse(Representation rep, ItemDestination dest)
throws IOException,XMLException
{
parse(rep,null,dest);
}
public void parse(Representation rep, URI baseURI, ItemDestination dest)
throws IOException,XMLException
{
String charset = rep.getMediaType().getParameters().getFirstValue("charset");
if (charset==null) {
charset = "UTF-8";
}
Reader r = new InputStreamReader(rep.getStream(),charset);
if (validate) {
dest = createValidationFilter(dest);
}
loader.generate(r,baseURI,dest);
}
public Document load(Response response)
throws IOException,XMLException
{
DocumentDestination dest = new DocumentDestination();
parse(response,dest);
return dest.getDocument();
}
public Document load(Representation rep)
throws IOException,XMLException
{
DocumentDestination dest = new DocumentDestination();
parse(rep,null,dest);
return dest.getDocument();
}
public static boolean isXML(MediaType type)
{
String name = type!=null ? type.getName() : null;
return MediaType.TEXT_XML.getName().equals(name) || MediaType.APPLICATION_XML.getName().equals(name);
}
public static boolean isXMLTyped(MediaType type)
{
String name = type!=null ? type.getName() : null;
return name!=null && name.endsWith("+xml");
}
}