package com.mysema.rdfbean.model.io;
import java.io.IOException;
import java.io.Writer;
import java.util.Map;
import javax.annotation.Nullable;
import com.mysema.commons.l10n.support.LocaleUtil;
import com.mysema.rdfbean.model.LIT;
import com.mysema.rdfbean.model.RDF;
import com.mysema.rdfbean.model.RepositoryException;
import com.mysema.rdfbean.model.STMT;
import com.mysema.rdfbean.model.UID;
/**
* @author tiwe
*
*/
public class RDFXMLWriter implements RDFWriter {
private final Writer writer;
private final Map<String, String> prefixes;
@Nullable
private STMT last;
public RDFXMLWriter(Writer writer, Map<String, String> prefixes) {
this.writer = writer;
this.prefixes = prefixes;
}
@Override
public void begin() {
try {
writer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
writer.append("<!DOCTYPE rdf:RDF [\n");
for (Map.Entry<String, String> entry : prefixes.entrySet()) {
writer.append("<!ENTITY " + entry.getValue() + " \"" + entry.getKey() + "\">\n");
}
writer.append("]>\n");
writer.append("<rdf:RDF xmlns:rdf=\"&rdf;\"");
for (Map.Entry<String, String> entry : prefixes.entrySet()) {
if (!entry.getKey().equals(RDF.NS)) {
writer.append(" xmlns:" + entry.getValue() + "=\"&" + entry.getValue() + ";\"");
}
}
writer.append(">\n");
} catch (IOException e) {
throw new RepositoryException(e);
}
}
@Override
public void end() {
try {
if (last != null) {
writer.append(" </rdf:Description>\n");
}
writer.append("</rdf:RDF>\n");
writer.flush();
} catch (IOException e) {
throw new RepositoryException(e);
}
}
@Override
public void handle(STMT stmt) {
try {
if (last == null || !last.getSubject().equals(stmt.getSubject())) {
if (last != null) {
writer.append(" </rdf:Description>\n");
}
writer.append(" <rdf:Description");
if (stmt.getSubject().isURI()) {
writer.append(" rdf:about=\"" + shorten(stmt.getSubject().asURI()) + "\">\n");
} else {
writer.append(" rdf:nodeID=\"" + stmt.getSubject().getId() + "\">\n");
}
}
String prefix = prefixes.get(stmt.getPredicate().ns());
if (prefix == null) {
prefix = "ns";
writer.append(" <" + prefix + ":" + stmt.getPredicate().ln() + " xmlns:ns=\"" + stmt.getPredicate().ns() + "\"");
} else {
writer.append(" <" + prefix + ":" + stmt.getPredicate().ln());
}
if (stmt.getObject().isLiteral()) {
LIT lit = stmt.getObject().asLiteral();
if (lit.getLang() != null) {
writer.append(" xml:lang=\"" + LocaleUtil.toLang(lit.getLang()) + "\"");
} else {
writer.append(" rdf:datatype=\"" + shorten(lit.getDatatype()) + "\"");
}
writer.append(">");
appendEscaped(stmt.getObject().getValue());
writer.append("</" + prefix + ":" + stmt.getPredicate().ln() + ">\n");
} else if (stmt.getObject().isBNode()) {
writer.append(" rdf:nodeID=\"" + stmt.getObject().getValue() + "\"/>\n");
} else {
writer.append(" rdf:resource=\"" + shorten(stmt.getObject().asURI()) + "\"/>\n");
}
last = stmt;
} catch (IOException e) {
throw new RepositoryException(e);
}
}
private String shorten(UID uid) {
if (prefixes.containsKey(uid.ns())) {
return "&" + prefixes.get(uid.ns()) + ";" + uid.ln();
} else {
return uid.getId();
}
}
private void appendEscaped(String val) throws IOException {
for (int i = 0; i < val.length(); ++i) {
char c = val.charAt(i);
if (c == '&') {
writer.write("&");
} else if (c == '<') {
writer.write("<");
} else if (c == '>') {
writer.write(">");
} else if (c == '"') {
writer.write(""");
} else if (c == '\'') {
writer.write("'");
} else {
writer.write(c);
}
}
}
}