/*******************************************************************************
* Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* File: $Source: /cvsroot/slrp/boca/com.ibm.adtech.boca.common/src/com/ibm/adtech/boca/serialization/BocaXMLNodeWriter.java,v $
* Created by: Matthew Roy ( <a href="mailto:mroy@us.ibm.com">mroy@us.ibm.com </a>)
* Created on: 5/1/2006
* Revision: $Id: XMLNodeWriter.java 178 2007-07-31 14:22:33Z mroy $
*
* Contributors:
* IBM Corporation - initial API and implementation
* Cambridge Semantics Incorporated - Fork to Anzo
*******************************************************************************/
package org.openanzo.services.serialization;
import java.io.IOException;
import java.io.Writer;
import org.apache.commons.codec.binary.Base64;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.rdf.BlankNode;
import org.openanzo.rdf.Constants;
import org.openanzo.rdf.Literal;
import org.openanzo.rdf.PlainLiteral;
import org.openanzo.rdf.Resource;
import org.openanzo.rdf.Statement;
import org.openanzo.rdf.TypedLiteral;
import org.openanzo.rdf.URI;
import org.openanzo.rdf.Value;
import org.openanzo.rdf.utils.SerializationConstants;
import org.openanzo.services.INamedGraphUpdate;
import org.openanzo.services.IUpdateTransaction;
import org.openanzo.services.serialization.CommonSerializationUtils.NodeType;
/**
* Provides XML serialization of transport messages.
*
* @author Matthew Roy ( <a href="mailto:mroy@cambridgesemantics.com">mroy@cambridgesemantics.com </a>)
*
*/
public class XMLWritingUtils {
protected static void handleTransaction(Writer out, boolean includeContents, IUpdateTransaction transaction) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.transaction);
writeAttribute(out, SerializationConstants.transactionURI, transaction.getURI().toString());
writeAttribute(out, SerializationConstants.transactionTimestamp, Long.toString(transaction.getTransactionTimestamp()));
writeCloseElement(out, true);
if (transaction.getUpdatedNamedGraphRevisions() != null) {
writeStartElement(out, SerializationConstants.namedGraphUpdates);
writeCloseElement(out, false);
writeValue(out, CommonSerializationUtils.writeNamedGraphRevisions(transaction.getUpdatedNamedGraphRevisions()));
writeEndElement(out, SerializationConstants.namedGraphUpdates);
}
if (transaction.getTransactionContext() != null) {
writeStartElement(out, SerializationConstants.transactionContext);
writeCloseElement(out, false);
for (Statement stmt : transaction.getTransactionContext()) {
handleStatement(out, stmt);
}
writeEndElement(out, SerializationConstants.transactionContext);
}
if (transaction.getErrors() != null && transaction.getErrors().size() > 0) {
for (AnzoException ae : transaction.getErrors()) {
handleError(out, ae.getErrorCode(), ae.getArgs());
}
}
if (includeContents) {
if (transaction.getPreconditions() != null) {
handlePreconditionsStart(out);
for (Statement stmt : CommonSerializationUtils.serializePreconditions(transaction.getPreconditions())) {
handleStatement(out, stmt);
}
handlePreconditionsEnd(out);
}
for (INamedGraphUpdate update : transaction.getNamedGraphUpdates()) {
handleNamedGraphUpdate(out, update);
}
}
writeEndElement(out, SerializationConstants.transaction);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void handleNamedGraphUpdate(Writer out, INamedGraphUpdate update) throws AnzoException {
try {
handleNamedGraphStart(out, update.getNamedGraphURI(), update.getUUID(), update.getRevision());
writeStartElement(out, SerializationConstants.additions);
writeCloseElement(out, true);
for (Statement stmt : update.getAdditions()) {
handleStatement(out, stmt);
}
writeEndElement(out, SerializationConstants.additions);
writeStartElement(out, SerializationConstants.metaAdditions);
writeCloseElement(out, true);
for (Statement stmt : update.getMetaAdditions()) {
handleStatement(out, stmt);
}
writeEndElement(out, SerializationConstants.metaAdditions);
writeStartElement(out, SerializationConstants.removals);
writeCloseElement(out, true);
for (Statement stmt : update.getRemovals()) {
handleStatement(out, stmt);
}
writeEndElement(out, SerializationConstants.removals);
writeStartElement(out, SerializationConstants.metaRemovals);
writeCloseElement(out, true);
for (Statement stmt : update.getMetaRemovals()) {
handleStatement(out, stmt);
}
writeEndElement(out, SerializationConstants.metaRemovals);
handleNamedGraphEnd(out);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void start(Writer out) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.payload);
writeCloseElement(out, true);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void end(Writer out) throws AnzoException {
try {
writeEndElement(out, SerializationConstants.payload);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static private void handlePreconditionsStart(Writer out) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.preconditions);
writeCloseElement(out, true);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static private void handlePreconditionsEnd(Writer out) throws AnzoException {
try {
writeEndElement(out, SerializationConstants.preconditions);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void handleNamedGraphStart(Writer out, URI namedGraphUri, URI uuid, long revision) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.namedGraph);
writeAttribute(out, SerializationConstants.revision, Long.toString(revision));
writeAttribute(out, SerializationConstants.namedGraphUri, namedGraphUri.toString());
if (uuid != null)
writeAttribute(out, SerializationConstants.namedGraphUUID, uuid.toString());
writeCloseElement(out, true);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void handleNamedGraphEnd(Writer out) throws AnzoException {
try {
writeEndElement(out, SerializationConstants.namedGraph);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static private void handleStatement(Writer out, Statement statement) throws AnzoException {
handleStatement(out, statement.getSubject(), statement.getPredicate(), statement.getObject(), statement.getNamedGraphUri());
}
/**
* Write out a statement
*
* @param out
* writer for data
* @param subject
* subject of statement
* @param predicate
* predicate of statement
* @param object
* object of statement
* @param ngURI
* namedgraph URI of statement
* @throws AnzoException
*/
static public void handleStatement(Writer out, Resource subject, URI predicate, Value object, URI ngURI) throws AnzoException {
handleStatement(out, subject, predicate, object, ngURI, null, null);
}
/**
* Write out a statement
*
* @param out
* writer for data
* @param subject
* subject of statement
* @param predicate
* predicate of statement
* @param object
* object of statement
* @param ngURI
* namedgraph URI of statement
* @param start
* what revision this statement was added
* @param end
* what revision this statement was removed
* @throws AnzoException
*/
static public void handleStatement(Writer out, Resource subject, URI predicate, Value object, URI ngURI, Long start, Long end) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.statement);
if (start != null) {
writeAttribute(out, SerializationConstants.start, start.toString());
}
if (end != null) {
writeAttribute(out, SerializationConstants.end, end.toString());
}
writeCloseElement(out, true);
writeStartElement(out, SerializationConstants.subject);
if (subject instanceof URI) {
writeAttribute(out, SerializationConstants.subjectType, NodeType.URI.name());
writeCloseElement(out, false);
writeValue(out, subject.toString());
} else {
writeAttribute(out, SerializationConstants.subjectType, NodeType.BNODE.name());
writeCloseElement(out, false);
writeValue(out, (((BlankNode) subject).getLabel()));
}
writeEndElement(out, SerializationConstants.subject);
writeStartElement(out, SerializationConstants.predicate);
writeCloseElement(out, false);
writeValue(out, predicate.toString());
writeEndElement(out, SerializationConstants.predicate);
writeStartElement(out, SerializationConstants.object);
if (object instanceof Literal) {
writeAttribute(out, SerializationConstants.objectType, NodeType.LITERAL.name());
Literal literal = (Literal) object;
if (literal instanceof TypedLiteral) {
URI dt = ((TypedLiteral) literal).getDatatypeURI();
writeAttribute(out, SerializationConstants.dataType, dt.toString());
} else if (literal instanceof PlainLiteral) {
String lang = ((PlainLiteral) literal).getLanguage();
if (lang != null)
writeAttribute(out, SerializationConstants.language, lang);
}
writeCloseElement(out, false);
writeEncodedValue(out, literal.getLabel());
} else if (object instanceof URI) {
writeAttribute(out, SerializationConstants.objectType, NodeType.URI.name());
writeCloseElement(out, false);
writeValue(out, object.toString());
} else {
writeAttribute(out, SerializationConstants.objectType, NodeType.BNODE.name());
writeCloseElement(out, false);
writeValue(out, (((BlankNode) object).getLabel()));
}
writeEndElement(out, SerializationConstants.object);
if (ngURI != null) {
writeStartElement(out, SerializationConstants.namedGraphUri);
writeCloseElement(out, false);
writeValue(out, ngURI.toString());
writeEndElement(out, SerializationConstants.namedGraphUri);
}
writeEndElement(out, SerializationConstants.statement);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
private static void handleError(Writer out, long errorCode, String... errorMessageArgs) throws AnzoException {
try {
writeStartElement(out, SerializationConstants.errorResult);
writeAttribute(out, SerializationConstants.errorTags, "0");
writeAttribute(out, SerializationConstants.errorCode, errorCode + "");
writeCloseElement(out, true);
for (String arg : errorMessageArgs) {
writeStartElement(out, SerializationConstants.errorMessageArg);
writeCloseElement(out, true);
writeValue(out, arg);
writeEndElement(out, SerializationConstants.errorMessageArg);
}
writeEndElement(out, SerializationConstants.errorResult);
} catch (IOException e) {
throw new AnzoException(ExceptionConstants.IO.WRITE_ERROR, e.getMessage());
}
}
static protected void writeStartElement(Writer out, String elementName) throws IOException {
out.write("<");
out.write(elementName);
out.write(" ");
}
static protected void writeCloseElement(Writer out, boolean newLine) throws IOException {
out.write('>');
if (newLine) {
out.write('\n');
}
}
static protected void writeCloseEndElement(Writer out) throws IOException {
out.write("/>\n");
}
static protected void writeEndElement(Writer out, String elementName) throws IOException {
out.write("</");
out.write(elementName);
out.write(">\n");
}
static protected void writeAttribute(Writer out, String attributeName, String value) throws IOException {
out.write(attributeName);
out.write("=\"");
out.write(value);
out.write("\" ");
}
static protected void writeValue(Writer out, String value) throws IOException {
out.write("<![CDATA[");
out.write(value);
out.write("]]>");
}
static protected void writeEncodedValue(Writer out, String value) throws IOException {
out.write("<![CDATA[");
out.write(new String(Base64.encodeBase64(value.getBytes(Constants.byteEncoding)), Constants.byteEncoding));
out.write("]]>");
}
}