All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.rdf4j.http.protocol.transaction.TransactionSAXParser Maven / Gradle / Ivy

There is a newer version: 5.1.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Distribution License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *******************************************************************************/
package org.eclipse.rdf4j.http.protocol.transaction;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.eclipse.rdf4j.common.xml.SimpleSAXAdapter;
import org.eclipse.rdf4j.http.protocol.transaction.operations.AddStatementOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearNamespacesOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.ClearOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveNamespaceOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.RemoveStatementsOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.SPARQLUpdateOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.SetNamespaceOperation;
import org.eclipse.rdf4j.http.protocol.transaction.operations.TransactionOperation;
import org.eclipse.rdf4j.model.IRI;
import org.eclipse.rdf4j.model.Literal;
import org.eclipse.rdf4j.model.Resource;
import org.eclipse.rdf4j.model.Value;
import org.eclipse.rdf4j.model.ValueFactory;
import org.eclipse.rdf4j.model.impl.SimpleValueFactory;
import org.eclipse.rdf4j.query.Binding;
import org.eclipse.rdf4j.query.impl.SimpleBinding;
import org.eclipse.rdf4j.query.impl.SimpleDataset;
import org.xml.sax.SAXException;

/**
 * Parses an RDF transaction document into a collection of {@link TransactionOperation} objects.
 * 
 * @author Arjohn Kampman
 * @author Leo Sauermann
 */
class TransactionSAXParser extends SimpleSAXAdapter {

	private ValueFactory valueFactory;

	protected Collection txn;

	private List parsedValues = new ArrayList();

	private List bindings;

	private SPARQLUpdateOperation currentSPARQLUpdate = null;

	private SimpleDataset currentDataset;

	public TransactionSAXParser() {
		this(SimpleValueFactory.getInstance());
	}

	public TransactionSAXParser(ValueFactory valueFactory) {
		this.valueFactory = valueFactory;
	}

	/**
	 * get the parsed transaction
	 * 
	 * @return the parsed transaction
	 */
	public Collection getTxn() {
		return txn;
	}

	@Override
	public void startDocument()
		throws SAXException
	{
		txn = new ArrayList();
	}

	@Override
	public void startTag(String tagName, Map atts, String text)
		throws SAXException
	{
		if (TransactionXMLConstants.URI_TAG.equals(tagName)) {
			parsedValues.add(valueFactory.createIRI(text));
		}
		else if (TransactionXMLConstants.BNODE_TAG.equals(tagName)) {
			parsedValues.add(valueFactory.createBNode(text));
		}
		else if (TransactionXMLConstants.LITERAL_TAG.equals(tagName)) {
			String lang = atts.get(TransactionXMLConstants.LANG_ATT);
			String datatype = atts.get(TransactionXMLConstants.DATATYPE_ATT);
			String encoding = atts.get(TransactionXMLConstants.ENCODING_ATT);

			if (encoding != null && "base64".equalsIgnoreCase(encoding)) {
				text = new String(javax.xml.bind.DatatypeConverter.parseBase64Binary(text));
			}
			Literal lit;
			if (lang != null) {
				lit = valueFactory.createLiteral(text, lang);
			}
			else if (datatype != null) {
				IRI dtURI = valueFactory.createIRI(datatype);
				lit = valueFactory.createLiteral(text, dtURI);
			}
			else {
				lit = valueFactory.createLiteral(text);
			}

			parsedValues.add(lit);
		}
		else if (TransactionXMLConstants.NULL_TAG.equals(tagName)) {
			parsedValues.add(null);
		}
		else if (TransactionXMLConstants.SET_NAMESPACE_TAG.equals(tagName)) {
			String prefix = atts.get(TransactionXMLConstants.PREFIX_ATT);
			String name = atts.get(TransactionXMLConstants.NAME_ATT);
			txn.add(new SetNamespaceOperation(prefix, name));
		}
		else if (TransactionXMLConstants.REMOVE_NAMESPACE_TAG.equals(tagName)) {
			String prefix = atts.get(TransactionXMLConstants.PREFIX_ATT);
			txn.add(new RemoveNamespaceOperation(prefix));
		}
		else if (TransactionXMLConstants.CLEAR_NAMESPACES_TAG.equals(tagName)) {
			txn.add(new ClearNamespacesOperation());
		}
		else if (TransactionXMLConstants.SPARQL_UPDATE_TAG.equals(tagName)) {
			if (currentSPARQLUpdate != null) {
				throw new SAXException("unexpected start of SPARQL Update operation");
			}
			currentSPARQLUpdate = new SPARQLUpdateOperation();

			String baseURI = atts.get(TransactionXMLConstants.BASE_URI_ATT);
			boolean includeInferred = Boolean.parseBoolean(
					atts.get(TransactionXMLConstants.INCLUDE_INFERRED_ATT));

			currentSPARQLUpdate.setIncludeInferred(includeInferred);
			currentSPARQLUpdate.setBaseURI(baseURI);
		}
		else if (TransactionXMLConstants.UPDATE_STRING_TAG.equals(tagName)) {
			currentSPARQLUpdate.setUpdateString(text);
		}
		else if (TransactionXMLConstants.DATASET_TAG.equals(tagName)) {
			currentDataset = new SimpleDataset();
		}
		else if (TransactionXMLConstants.DEFAULT_INSERT_GRAPH.equals(tagName)) {
			currentDataset.setDefaultInsertGraph(valueFactory.createIRI(text));
		}
		else if (TransactionXMLConstants.GRAPH_TAG.equals(tagName)) {
			parsedValues.add(valueFactory.createIRI(text));
		}
		else if (TransactionXMLConstants.BINDINGS.equals(tagName)) {
			if (bindings != null) {
				throw new SAXException("unexpected start of SPARQL Update operation bindings");
			}

			bindings = new ArrayList();
		}
		else if (TransactionXMLConstants.BINDING_URI.equals(tagName)
				|| TransactionXMLConstants.BINDING_BNODE.equals(tagName)
				|| TransactionXMLConstants.BINDING_LITERAL.equals(tagName))
		{
			if (bindings == null) {
				throw new SAXException(
						"unexpected start of SPARQL Update operation binding (without )");
			}

			String value = text;
			String name = atts.get(TransactionXMLConstants.NAME_ATT);

			if (name != null && value != null) {
				Value v;

				if (TransactionXMLConstants.BINDING_URI.equals(tagName)) {
					v = valueFactory.createIRI(value);
				}
				else if (TransactionXMLConstants.BINDING_BNODE.equals(tagName)) {
					v = valueFactory.createBNode(value);
				}
				else {
					String language = atts.get(TransactionXMLConstants.LANGUAGE_ATT);
					String dataType = atts.get(TransactionXMLConstants.DATA_TYPE_ATT);

					if (language != null) {
						v = valueFactory.createLiteral(value, language);
					}
					else if (dataType != null) {
						v = valueFactory.createLiteral(value, valueFactory.createIRI(dataType));
					}
					else {
						v = valueFactory.createLiteral(value);
					}
				}
				bindings.add(new SimpleBinding(name, v));
			}
		}
	}

	@Override
	public void endTag(String tagName)
		throws SAXException
	{
		if (TransactionXMLConstants.ADD_STATEMENT_TAG.equals(tagName)) {
			txn.add(createAddStatementOperation());
		}
		else if (TransactionXMLConstants.REMOVE_STATEMENTS_TAG.equals(tagName)) {
			txn.add(createRemoveStatementsOperation());
		}
		else if (TransactionXMLConstants.CLEAR_TAG.equals(tagName)) {
			txn.add(createClearOperation());
		}
		else if (TransactionXMLConstants.SPARQL_UPDATE_TAG.equals(tagName)) {
			txn.add(currentSPARQLUpdate);
			currentSPARQLUpdate = null;
		}
		else if (TransactionXMLConstants.DEFAULT_GRAPHS_TAG.equals(tagName)) {
			for (Value parsedValue : parsedValues) {
				try {
					currentDataset.addDefaultGraph((IRI)parsedValue);
				}
				catch (ClassCastException e) {
					throw new SAXException("unexpected value in default graph list: " + parsedValue);
				}
			}
			parsedValues.clear();
		}
		else if (TransactionXMLConstants.NAMED_GRAPHS_TAG.equals(tagName)) {
			for (Value parsedValue : parsedValues) {
				try {
					currentDataset.addNamedGraph((IRI)parsedValue);
				}
				catch (ClassCastException e) {
					throw new SAXException("unexpected value in named graph list: " + parsedValue);
				}
			}
			parsedValues.clear();
		}
		else if (TransactionXMLConstants.DEFAULT_REMOVE_GRAPHS_TAG.equals(tagName)) {
			for (Value parsedValue : parsedValues) {
				try {
					currentDataset.addDefaultRemoveGraph((IRI)parsedValue);
				}
				catch (ClassCastException e) {
					throw new SAXException("unexpected value in default remove graph list: " + parsedValue);
				}
			}
			parsedValues.clear();
		}
		else if (TransactionXMLConstants.DATASET_TAG.equals(tagName)) {
			currentSPARQLUpdate.setDataset(currentDataset);
			currentDataset = null;
		}
		else if (TransactionXMLConstants.BINDINGS.equals(tagName)) {
			Binding b[] = bindings.toArray(new Binding[0]);
			currentSPARQLUpdate.setBindings(b);
			bindings.clear();
			bindings = null;
		}
	}

	private TransactionOperation createClearOperation()
		throws SAXException
	{
		Resource[] contexts = createContexts(0);
		parsedValues.clear();

		return new ClearOperation(contexts);
	}

	private TransactionOperation createAddStatementOperation()
		throws SAXException
	{
		if (parsedValues.size() < 3) {
			throw new SAXException("At least three values required for AddStatementOperation, found: "
					+ parsedValues.size());
		}

		try {
			Resource subject = (Resource)parsedValues.get(0);
			IRI predicate = (IRI)parsedValues.get(1);
			Value object = parsedValues.get(2);
			Resource[] contexts = createContexts(3);

			parsedValues.clear();

			if (subject == null || predicate == null || object == null) {
				throw new SAXException(
						"Subject, predicate and object cannot be null for an AddStatementOperation");
			}
			return new AddStatementOperation(subject, predicate, object, contexts);
		}
		catch (ClassCastException e) {
			throw new SAXException("Invalid argument(s) for AddStatementOperation", e);
		}
	}

	private TransactionOperation createRemoveStatementsOperation()
		throws SAXException
	{
		if (parsedValues.size() < 3) {
			throw new SAXException("At least three values required for RemoveStatementsOperation, found: "
					+ parsedValues.size());
		}

		try {
			Resource subject = (Resource)parsedValues.get(0);
			IRI predicate = (IRI)parsedValues.get(1);
			Value object = parsedValues.get(2);
			Resource[] contexts = createContexts(3);

			parsedValues.clear();

			return new RemoveStatementsOperation(subject, predicate, object, contexts);
		}
		catch (ClassCastException e) {
			throw new SAXException("Invalid argument(s) for RemoveStatementsOperation", e);
		}
	}

	private Resource[] createContexts(int startIdx)
		throws SAXException
	{
		List contexts = new ArrayList();

		for (int i = startIdx; i < parsedValues.size(); i++) {
			Value contextCandidate = parsedValues.get(i);

			if (contextCandidate == null || contextCandidate instanceof Resource) {
				contexts.add((Resource)contextCandidate);
			}
			else {
				throw new SAXException("Invalid context value: " + contextCandidate.getClass());
			}
		}

		return contexts.toArray(new Resource[contexts.size()]);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy