[Mulgara-svn] r1973 - in trunk/src/jar: . content-rdfa content-rdfa/java content-rdfa/java/org content-rdfa/java/org/mulgara content-rdfa/java/org/mulgara/content content-rdfa/java/org/mulgara/content/rdfa

pag at mulgara.org pag at mulgara.org
Fri Aug 20 02:41:38 UTC 2010


Author: pag
Date: 2010-08-20 02:41:38 +0000 (Fri, 20 Aug 2010)
New Revision: 1973

Added:
   trunk/src/jar/content-rdfa/
   trunk/src/jar/content-rdfa/build.xml
   trunk/src/jar/content-rdfa/content-rdfa-build.properties
   trunk/src/jar/content-rdfa/java/
   trunk/src/jar/content-rdfa/java/org/
   trunk/src/jar/content-rdfa/java/org/mulgara/
   trunk/src/jar/content-rdfa/java/org/mulgara/content/
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/BasedResolver.java
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaContentHandler.java
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatements.java
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatementsUnitTest.java
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/StatementParser.java
   trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/package.html
Log:
Fixing the RDFa code that should have already been added

Added: trunk/src/jar/content-rdfa/build.xml
===================================================================
--- trunk/src/jar/content-rdfa/build.xml	                        (rev 0)
+++ trunk/src/jar/content-rdfa/build.xml	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!DOCTYPE project>
+
+<!-- =================================================================== -->
+<!--                       Project definition                            -->
+<!-- =================================================================== -->
+<project name="content-rdfa" default="content-rdfa-jar" basedir="../../..">
+
+  <!-- =================================================================== -->
+  <!--                      Property Definitions                           -->
+  <!-- =================================================================== -->
+
+  <!-- =================================================================== -->
+  <!--                              Imports                                -->
+  <!-- =================================================================== -->
+
+  <!-- =================================================================== -->
+  <!--                          Path Definitions                           -->
+  <!-- =================================================================== -->
+  <path id="content-rdfa-classpath">
+    <path refid="common-classpath"/>
+    <fileset file="${query.dist.dir}/${query.jar}"/>
+    <fileset file="${resolver-spi.dist.dir}/${resolver-spi.jar}"/>
+    <fileset file="${resolver-file.dist.dir}/${resolver-file.jar}"/>
+    <fileset file="${tuples.dist.dir}/${tuples.jar}"/>
+    <fileset file="${util.dist.dir}/${util.jar}"/>
+    <fileset file="${lib.dir}/${htmlparser.jar}"/>
+    <fileset file="${lib.dir}/${java-rdfa.jar}"/>
+  </path>
+
+  <path id="content-rdfa-test-classpath">
+    <path refid="content-rdfa-classpath"/>
+    <fileset file="${resolver-file.dist.dir}/${resolver-file.jar}"/>
+    <fileset file="${store-stringpool-memory.dist.dir}/${store-stringpool-memory.jar}"/>
+    <fileset file="${store-stringpool-xa.dist.dir}/${store-stringpool-xa.jar}"/>
+    <fileset file="${content-rdfa.dist.dir}/${content-rdfa.jar}"/>
+  </path>
+
+
+  <target name="content-rdfa-clean" description="Removes all compile generated files for content-rdfa">
+    <tstamp/>
+    <delete dir="${content-rdfa.obj.dir}"/>
+    <delete dir="${content-rdfa.test.dir}"/>
+    <delete dir="${content-rdfa.dist.dir}"/>
+  </target>
+
+
+  <target name="-content-rdfa-prepare"
+          description="Creates all directories associated with the content-rdfa's compilation"
+          depends="-prepare-build">
+    <mkdir dir="${content-rdfa.obj.dir}"/>
+    <mkdir dir="${content-rdfa.test.dir}"/>
+    <mkdir dir="${content-rdfa.dist.dir}"/>
+    <mkdir dir="${content-rdfa.obj.dir}/classes"/>
+  </target>
+
+
+  <target name="content-rdfa-compile"
+          depends="-content-rdfa-prepare, resolver-spi-jar, resolver-file-jar"
+          description="Compiles all content-rdfa related files">
+    <javac destdir="${content-rdfa.obj.dir}/classes" debug="on" deprecation="on" source="1.5" encoding="UTF-8">
+      <classpath refid="content-rdfa-classpath"/>
+      <src path="${content-rdfa.src.dir}/java"/>
+    </javac>
+  </target>
+
+
+  <target name="content-rdfa-jar" depends="content-rdfa-compile, -content-rdfa-jar-uptodate"
+          unless="content-rdfa.jar.uptodate" description="Builds the rdfa content handler JAR">
+
+    <jar jarfile="${content-rdfa.dist.dir}/${content-rdfa.jar}">
+      <fileset dir="${content-rdfa.obj.dir}/classes"/>
+      <zipfileset src="${lib.dir}/${htmlparser.jar}" excludes="META-INF/**"/>
+      <zipfileset src="${lib.dir}/${java-rdfa.jar}" excludes="META-INF/**"/>
+    </jar>
+  </target>
+
+
+  <target name="-content-rdfa-jar-uptodate">
+    <uptodate property="content-rdfa.jar.uptodate" targetfile="${content-rdfa.dist.dir}/${content-rdfa.jar}">
+      <srcfiles dir="${content-rdfa.obj.dir}/classes" includes="**/*"/>
+    </uptodate>
+  </target>
+
+
+  <target name="content-rdfa-dist" depends="content-rdfa-jar" unless="content-rdfa.uptodate"
+          description="Performs all tasks related to finalising this content-rdfa and readying it for distribution">
+  </target>
+
+
+  <target name="content-rdfa-test"
+          depends="content-rdfa-jar, resolver-file-jar, store-stringpool-memory-jar, store-stringpool-xa-jar">
+    <antcall target="component-test">
+      <param name="classpath.id" value="content-rdfa-test-classpath"/>
+      <param name="dir" value="${content-rdfa.src.dir}"/>
+      <param name="jar" value="${content-rdfa.jar}"/>
+    </antcall>
+  </target>
+
+
+  <target name="content-rdfa-javadoc" depends="content-rdfa-jar" description="Creates the javadoc for this content-rdfa">
+    <antcall target="javadoc">
+      <param name="javadoc.package" value="org.mulgara.content.rdfa.*"/>
+      <param name="javadoc.classpath" value="content-rdfa-classpath"/>
+      <param name="javadoc.sourcepath" value="${content-rdfa.src.dir}/java"/>
+    </antcall>
+  </target>
+
+
+  <target name="content-rdfa-help" description="Displays the help information for this content-rdfa">
+    <echo message="Welcome to the build script for ${content-rdfa.name}."/>
+    <echo message=""/>
+    <echo message="These targets can be invoked as follows:"/>
+    <echo message="  ./build.sh &lt;target&gt;"/>
+    <echo message=""/>
+    <java fork="false" classname="org.apache.tools.ant.Main" newenvironment="false">
+      <jvmarg value="${arch.bits}"/>
+      <arg line="-buildfile ${content-rdfa.src.dir}/build.xml -projecthelp"/>
+    </java>
+  </target>
+
+</project>

Added: trunk/src/jar/content-rdfa/content-rdfa-build.properties
===================================================================
--- trunk/src/jar/content-rdfa/content-rdfa-build.properties	                        (rev 0)
+++ trunk/src/jar/content-rdfa/content-rdfa-build.properties	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,14 @@
+#
+# Properties used by the RDFa content handler module
+#
+
+# Module Name
+content-rdfa.name          = Content RDFa
+
+# General module properties
+content-rdfa.src.dir       = ${jar.src.dir}/content-rdfa
+content-rdfa.obj.dir       = ${jar.obj.dir}/content-rdfa
+content-rdfa.dist.dir      = ${bin.dir}
+content-rdfa.test.dir      = ${test.dir}/content-rdfa
+content-rdfa.jxtest.dir    = ${jxtest.dir}/content-rdfa
+content-rdfa.jar           = content-rdfa-base-${mulgara-version}.jar

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/BasedResolver.java
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/BasedResolver.java	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/BasedResolver.java	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2010 Paul Gearon
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.content.rdfa;
+
+import org.apache.log4j.Logger;      // Apache Log4J
+
+import com.hp.hpl.jena.iri.IRI;
+import com.hp.hpl.jena.iri.IRIFactory;
+
+import net.rootdev.javardfa.Resolver;
+
+/**
+ *
+ * @created 2010-08-09
+ * @author Paul Gearon
+ */
+class BasedResolver implements Resolver {
+
+  /** Logger. */
+  @SuppressWarnings("unused")
+  private static final Logger logger = Logger.getLogger(BasedResolver.class.getName());
+
+  /** The factory for creating new IRIs. */
+  private final IRIFactory iriFactory;
+
+  /** The main IRI for determining relative IRIs in relation to. */
+  private IRI base;
+
+  /** The string if the IRI that is the base. */
+  private String baseStr;
+
+  /**
+   * Constructs a resolver with just the base.
+   * @param baseStr The string for the IRI to use as the base of relative IRIs.
+   */
+  public BasedResolver(String baseStr) {
+    this(baseStr, IRIFactory.semanticWebImplementation());
+  }
+
+  /**
+   * Constructs a resolver.
+   * @param baseStr The string for the IRI to use as the base of relative IRIs.
+   * @param iriFactory The factory for creating IRIs from.
+   */
+  public BasedResolver(String baseStr, IRIFactory iriFactory) {
+    this.iriFactory = iriFactory;
+    setBase(baseStr);
+  }
+
+  /**
+   * Changes the base to use.
+   * @param baseStr The new base. <code>null</code> will be ignored.
+   */
+  public void setBase(String baseStr) {
+    if (baseStr != null) {
+      this.baseStr = baseStr;
+      base = iriFactory.construct(baseStr);
+    }
+  }
+
+
+  /**
+   * Resolves a IRI relative to a given base.
+   * @param baseStr A string form of the base IRI. Expected to be the same as the current base.
+   * @param rel An IRI that may be relative to the base.
+   * @return a string containing the lexical form of the calculated IRI.
+   */
+  public String resolve(String baseStr, String rel) {
+    IRI bIri = base;
+    // test if a different base string to the one we expect is being used
+    if (baseStr != null) {
+      if (this.baseStr != baseStr && !baseStr.equals(this.baseStr)) {
+        bIri = iriFactory.construct(baseStr);
+      }
+    }
+    IRI resolved = bIri.resolve(rel);
+    return resolved.toString();
+  }
+
+}

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaContentHandler.java
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaContentHandler.java	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaContentHandler.java	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 Paul Gearon
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.content.rdfa;
+
+// Java packages
+// Java 2 enterprise packages
+import javax.activation.MimeType;
+import javax.activation.MimeTypeParseException;
+
+// Third party packages
+import org.apache.log4j.Logger;  // Apache Log4J
+
+// Local packages
+import org.mulgara.content.Content;
+import org.mulgara.content.ContentHandler;
+import org.mulgara.content.ContentHandlerException;
+import org.mulgara.content.ModifiedException;
+import org.mulgara.content.NotModifiedException;
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.resolver.spi.Statements;
+
+/**
+ * Resolves constraints in models defined by RDFa in HTML and XHTML documents
+ *
+ * @created 2010-08-09
+ * @author Paul Gearon
+ */
+public class RdfaContentHandler implements ContentHandler {
+  /** Logger. */
+  @SuppressWarnings("unused")
+  private static Logger logger = Logger.getLogger(RdfaContentHandler.class);
+
+  /** The MIME type for XHTML documents */
+  static final MimeType XHTML_MIME;
+
+  /** The MIME type for HTML documents */
+  static final MimeType HTML_MIME;
+
+  static {
+    try {
+      XHTML_MIME = new MimeType("application", "xml");
+      HTML_MIME = new MimeType("text", "html");
+    } catch (MimeTypeParseException e) {
+      throw new Error("Mime initialization error");
+    }
+  }
+
+  public Statements parse(Content content, ResolverSession resolverSession) throws ContentHandlerException {
+    try {
+      return new RdfaStatements(resolverSession, content);
+    } catch (Exception e) {
+      throw new ContentHandlerException(e.getMessage());
+    }
+  }
+
+  /**
+   * @return <code>true</code> if the file part of the URI has an
+   *   <code>.n3</code>, <code>.nt</code> or <code>.rdf</code> extension
+   */
+  public boolean canParse(Content content) throws NotModifiedException {
+    // We definitely can parse anything of MIME type application/rdf+xml
+    MimeType contentType = content.getContentType();
+    if (contentType != null && (HTML_MIME.match(contentType) || XHTML_MIME.match(contentType))) {
+      return true;
+    }
+
+    if (content.getURI() == null) return false;
+
+    // Obtain the path part of the URI
+    String path = content.getURI().getPath();
+    if (path == null) return false;
+    return path.endsWith(".html");
+  }
+
+  /**
+   * Cannot serialize RDF into HTML.
+   */
+  public void serialize(Statements      statements,
+                        Content         content,
+                        ResolverSession resolverSession)
+      throws ContentHandlerException, ModifiedException {
+    throw new UnsupportedOperationException();
+  }
+}

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatements.java
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatements.java	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatements.java	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2010 Paul Gearon.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mulgara.content.rdfa;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
+import org.jrdf.graph.Triple;
+import org.mulgara.content.Content;
+import org.mulgara.content.NotModifiedException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.resolver.spi.LocalizeException;
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.resolver.spi.Statements;
+import org.mulgara.store.tuples.AbstractTuples;
+import org.mulgara.store.tuples.Tuples;
+
+/**
+ * This class works in tandem with a parser to provide Statements with a cursor
+ * interface. The parser keeps a buffer, which this class sucks out of that
+ * buffer to provide statements as required.
+ */
+public class RdfaStatements extends AbstractTuples implements Statements {
+
+  /** The resolver session to convert parsed data into localized data. */
+  ResolverSession session;
+
+  /** The source of the statements. */
+  StatementParser source;
+
+  /** The current row. */
+  Triple currentRow = null;
+
+  /** Flag to indicate that the {@link #beforeFirst()} method has been called. */
+  boolean beforeFirstCalled = false;
+
+  /**
+   * Initialize the statements with the parser that is to be the source
+   * of the statements.
+   */
+  public RdfaStatements(ResolverSession session, Content content) throws TuplesException, NotModifiedException {
+    this.session = session;
+    source = new StatementParser(content, session);
+    new Thread(source).start();
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.Tuples#hasNoDuplicates()
+   */
+  public boolean hasNoDuplicates() throws TuplesException {
+    // no idea, so return false
+    return false;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.Tuples#getOperands()
+   */
+  public List<Tuples> getOperands() {
+    return Collections.emptyList();
+  }
+
+  /**
+   * @see org.mulgara.resolver.spi.Statements#getSubject()
+   */
+  @Override
+  public long getSubject() throws TuplesException {
+    SubjectNode s = currentRow.getSubject();
+    try {
+      return session.localize(s);
+    } catch (LocalizeException e) {
+      throw new TuplesException("Unable to localize subject: " + s);
+    }
+  }
+
+  /**
+   * @see org.mulgara.resolver.spi.Statements#getPredicate()
+   */
+  @Override
+  public long getPredicate() throws TuplesException {
+    PredicateNode p = currentRow.getPredicate();
+    try {
+      return session.localize(p);
+    } catch (LocalizeException e) {
+      throw new TuplesException("Unable to localize predicate: " + p);
+    }
+  }
+
+  /**
+   * @see org.mulgara.resolver.spi.Statements#getObject()
+   */
+  @Override
+  public long getObject() throws TuplesException {
+    ObjectNode o = currentRow.getObject();
+    try {
+      return session.localize(o);
+    } catch (LocalizeException e) {
+      throw new TuplesException("Unable to localize object: " + o);
+    }
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#getColumnValue(int)
+   */
+  @Override
+  public long getColumnValue(int column) throws TuplesException {
+    if (column == 0) return getSubject();
+    if (column == 1) return getPredicate();
+    if (column == 2) return getObject();
+    throw new IndexOutOfBoundsException("Statements have 3 columns: " + column);
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#getRowUpperBound()
+   */
+  public long getRowUpperBound() throws TuplesException {
+    // go for the max number of integers, not longs, since this is more reasonable
+    return source.isFinished() ? source.getStatementCount() : Integer.MAX_VALUE;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#getRowExpectedCount()
+   */
+  public long getRowExpectedCount() throws TuplesException {
+    return source.isFinished() ? source.getStatementCount() : Short.MAX_VALUE;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#isColumnEverUnbound(int)
+   */
+  public boolean isColumnEverUnbound(int column) throws TuplesException {
+    return false;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#beforeFirst(long[], int)
+   */
+  @Override
+  public void beforeFirst(long[] prefix, int suffixTruncation) throws TuplesException {
+    // Validate params
+    if (prefix != null && prefix.length != 0) {
+      throw new IllegalArgumentException("Prefix on RDFa statements must be empty");
+    }
+    if (suffixTruncation != 0) {
+      throw new IllegalArgumentException("Null \"suffixTruncation\" parameter");
+    }
+
+    if (beforeFirstCalled) throw new TuplesException("RDFa statements do not support rewinding");
+    beforeFirstCalled = true;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#next()
+   */
+  @Override
+  public boolean next() throws TuplesException {
+    try {
+      currentRow = source.getTriple();
+    } catch (TuplesException ex) {
+      source.terminate();
+      throw ex;
+    }
+
+    if (currentRow == null) {
+      rowCount = source.getStatementCount();
+      source.terminate();
+    }
+    return currentRow != null;
+  }
+
+  /**
+   * @see org.mulgara.store.tuples.AbstractTuples#close()
+   */
+  @Override
+  public void close() throws TuplesException {
+    source.terminate();
+  }
+
+}

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatementsUnitTest.java
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatementsUnitTest.java	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/RdfaStatementsUnitTest.java	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2010 Paul Gearon
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.content.rdfa;
+
+// Third party packages
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.activation.MimeType;
+import javax.activation.MimeTypeParseException;
+
+import junit.framework.*;        // JUnit unit testing framework
+import org.apache.log4j.Logger;  // Apache Log4J
+import org.jrdf.graph.AbstractTriple;
+import org.jrdf.graph.BlankNode;
+import org.jrdf.graph.URIReference;
+import org.jrdf.graph.Node;
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
+import org.jrdf.graph.Triple;
+import org.mulgara.content.Content;
+// import org.mulgara.resolver.http.HttpContent;
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.resolver.spi.Statements;
+import org.mulgara.resolver.spi.TestResolverSession;
+
+
+/**
+ * @created August 9, 2010
+ * @author Paul Gearon
+ */
+public class RdfaStatementsUnitTest extends TestCase {
+  /** Logger. */
+  @SuppressWarnings("unused")
+  private static final Logger logger = Logger.getLogger(RdfaStatementsUnitTest.class.getName());
+
+  //
+  // Constructors
+  //
+
+  /**
+   * Construct a test.
+   *
+   * @param name  the name of the test to construct
+   */
+  public RdfaStatementsUnitTest(String name) {
+    super(name);
+  }
+
+  //
+  // Methods implementing TestCase
+  //
+
+  public void setup() {
+  }
+
+  /**
+   * Hook from which the test runner can obtain a test suite.
+   *
+   * @return the test suite
+   */
+  public static Test suite() {
+    return new TestSuite(RdfaStatementsUnitTest.class);
+  }
+
+
+  /**
+   * Test {@link rdfaStatements} parsing a file.
+   */
+  public void testParse() throws Exception {
+    Content content = new StringContent(HCARD);
+    // Content content = new HttpContent(URI.create("http://examples.tobyinkster.co.uk/hcard"));
+    System.err.println(content.getContentType().toString());
+    StatementParser parser = new StatementParser(content, new TestResolverSession());
+    parser.run();
+  }
+
+  public void testParseData() throws Exception {
+    ResolverSession session = new TestResolverSession();
+    Content content = new StringContent(HCARD);
+    // Content content = new HttpContent(URI.create("http://examples.tobyinkster.co.uk/hcard"));
+    List<Triple> triples = toTriples(new RdfaStatements(session, content), session);
+    assertEquals(8, triples.size());
+    URI page = URI.create("http://examples.tobyinkster.co.uk/hcard");
+    for (int i = 0; i < 2; i++) assertEquals(page, ((URIReference)triples.get(i).getSubject()).getURI());
+    assertTrue(triples.get(2).getSubject().isBlankNode());
+    URI jack = URI.create("http://examples.tobyinkster.co.uk/hcard#jack");
+    for (int i = 3; i < 8; i++) {
+      assertTrue(triples.get(i).getSubject().isURIReference());
+      assertEquals(jack, ((URIReference)triples.get(i).getSubject()).getURI());
+    }
+  }
+
+  static List<Triple> toTriples(Statements s, ResolverSession session) throws Exception {
+    List<Triple> triples = new ArrayList<Triple>();
+    s.beforeFirst();
+    while (s.next()) {
+      triples.add(new TripleImpl(
+          session.globalize(s.getSubject()),
+          session.globalize(s.getPredicate()),
+          session.globalize(s.getObject())
+      ));
+    }
+    return triples;
+  }
+  
+  static final String HCARD = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML+RDFa 1.0//EN\"\n" +
+  "          \"http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd\">\n" +
+  "\n" +
+  "<html xml:lang=\"en\"\n" +
+  " xmlns=\"http://www.w3.org/1999/xhtml\"\n" +
+  " xmlns:vcard=\"urn:ietf:rfc:2426#\"\n" +
+  " xmlns:foaf=\"http://xmlns.com/foaf/0.1/\"\n" +
+  " xmlns:w3card=\"http://www.w3.org/2006/vcard/ns#\"\n" +
+  " xmlns:pim=\"http://www.w3.org/2000/10/swap/pim/contact#\"\n" +
+  " xmlns:dc=\"http://purl.org/dc/terms/\">\n" +
+  "\n" +
+  " <head>\n" +
+  "   <title>Complex hCard + RDFa Example</title>\n" +
+  "   <link rel=\"foaf:primaryTopic\" href=\"#jack\" />\n" +
+  " </head>\n" +
+  "\n" +
+  " <body style=\"max-width:50em\">\n" +
+  "\n" +
+  "   <p style=\"font-style:italic\">No, I'm not obsessed with Jack Bauer (well, maybe\n" +
+  "   a little bit). <span property=\"dc:abstract\">This page is intended to be a demonstration of\n" +
+  "   the use of RDFa (including FOAF, Dublin Core and W3C PIM vocabularies) in\n" +
+  "   conjunction with Microformats (including hCard and rel-tag).</span></p>\n" +
+  "\n" +
+  "   <div id=\"jack\" class=\"vcard\" typeof=\"pim:Male\">\n" +
+  "\n" +
+  "     <img class=\"photo\" alt=\"Jack could kick your ass.\" src=\"JackB4.jpg\" style=\"float:right;\n" +
+  "     margin:1em 0 1em 2em;    /* Don't let Jack too near the text as he might kick its ass! */\n" +
+  "     border: 4px solid black; /* But don't fool yourself into thinking that will constrain him! */\"\n" +
+  "     />\n" +
+  "\n" +
+  "     <h1 class=\"fn\">Jack Bauer</h1>\n" +
+  "\n" +
+  "     <p class=\"org\">\n" +
+  "       <span about=\"#jack\" property=\"w3card:category\" class=\"organization-name\">Counter-Terrorist Unit</span>\n" +
+  "       (<span class=\"organization-unit\">Los Angeles Division</span>)\n" +
+  "     </p>\n" +
+  "\n" +
+  "     <p class=\"adr\">\n" +
+  "       <span class=\"street-address\">10201 W. Pico Blvd.</span><br />\n" +
+  "       <span class=\"locality\">Los Angeles</span>,\n" +
+  "       <span class=\"region\">CA</span>\n" +
+  "       <span class=\"postal-code\">90064</span><br />\n" +
+  "       <span class=\"country-name\">United States</span><br />\n" +
+  "       <small class=\"geo\" style=\"color:#999;font-size:67%\">34.052339;-118.410623</small>\n" +
+  "     </p>\n" +
+  "\n" +
+  "     <h2>Assorted Contact Methods</h2>\n" +
+  "     <ul about=\"#jack\">\n" +
+  "       <li class=\"tel\">+1 (310) 597 3781 <span class=\"type\">work</span></li>\n" +
+  "       <li><a rel=\"tag foaf:homepage\" href=\"http://en.wikipedia.org/wiki/Jack_Bauer\">I'm on Wikipedia</a> so you can leave a message on my user talk page.</li>\n" +
+  "       <li rel=\"foaf:workInfoHomepage\"><a href=\"http://www.jackbauerfacts.com/\">Jack Bauer Facts</a></li>\n" +
+  "       <li class=\"email\">j.bauer at la.ctu.gov.invalid</li>\n" +
+  "       <li><a rel=\"w3card:mobileTel\" href=\"tel:+1-310-555-3781\">mobile phone</a></li>\n" +
+  "     </ul>\n" +
+  "\n" +
+  "     <p class=\"note\">If I'm out in the field, you may be better off contacting <span class=\"agent vcard\">\n" +
+  "     <a class=\"email fn\" href=\"mailto:c.obrian at la.ctu.gov.invalid\">Chloe O'Brian</a></span>\n" +
+  "     if it's about work, or ask <span class=\"agent\">Tony Almeida</span> if you're interested\n" +
+  "     in the CTU five-a-side football team we're trying to get going.</p>\n" +
+  "\n" +
+  "     <h2>Plan</h2>\n" +
+  "     <p about=\"#jack\" property=\"foaf:plan\">I will kick your terrorist ass!</p>\n" +
+  "\n" +
+  "     <ins class=\"tel rev\" datetime=\"2008-07-20T21:00:00+0100\">\n" +
+  "       <strong>Update!</strong>\n" +
+  "       My new <span class=\"type\">home</span> phone number is\n" +
+  "       <span class=\"value\">01632 960 123</span>.\n" +
+  "     </ins>\n" +
+  "   </div>\n" +
+  "\n" +
+  "\n" +
+  "   <div style=\"border-top: 1px solid silver;margin-top:2em;padding-top:0.67em\">\n" +
+  "\n" +
+  "     <a href=\"http://validator.w3.org/check?uri=referer\">validate</a> |\n" +
+  "\n" +
+  "     <a href=\"http://srv.buzzword.org.uk/vcard/referer\">cognify (vCard)</a> | \n" +
+  "\n" +
+  "     <a href=\"http://srv.buzzword.org.uk/jcard/referer\">cognify (jCard)</a> | \n" +
+  "\n" +
+  "     <a href=\"http://srv.buzzword.org.uk/rdf-xml/referer\">cognify (RDF)</a> | \n" +
+  "\n" +
+  "     tech:\n" +
+  "     <a href=\"http://rdfa.info/\"><img style=\"border:0;vertical-align:middle\" src=\"http://buzzword.org.uk/cognition/buttons/rdfa.png\" alt=\"RDFa,\" /></a>\n" +
+  "     <a href=\"http://www.foaf-project.org/\"><img style=\"border:0;vertical-align:middle\" src=\"http://buzzword.org.uk/cognition/buttons/foaf.png\" alt=\"FOAF,\" /></a>\n" +
+  "     <a href=\"http://dublincore.org/\"><img style=\"border:0;vertical-align:middle\" src=\"http://buzzword.org.uk/cognition/buttons/dc.png\" alt=\"Dublin Core and\" /></a>\n" +
+  "     <a href=\"http://microformats.org/wiki/hcard\"><img style=\"border:0;vertical-align:middle\" src=\"http://buzzword.org.uk/cognition/buttons/hcard.png\" alt=\"hCard\" /></a>\n" +
+  "\n" +
+  "   </div>\n" +
+  "\n" +
+  " </body>\n" +
+  "\n" +
+  "</html>\n";
+}
+
+class StringContent implements Content {
+  private final String content;
+
+  public StringContent(String content) {
+    this.content = content;
+  }
+
+  public Map<Object,BlankNode> getBlankNodeMap()         { return null; }
+  public MimeType getContentType()                       {
+    try {
+      return new MimeType("text", "html");
+    } catch (MimeTypeParseException e) { return null; }
+  }
+  public URI getURI()                                    { return URI.create("http://examples.tobyinkster.co.uk/hcard"); }
+  public String getURIString()                           { return "http://examples.tobyinkster.co.uk/hcard"; }
+  public OutputStream newOutputStream()                  { return null; }
+
+  public InputStream newInputStream() throws IOException {
+    return new ByteArrayInputStream(content.getBytes("UTF-8"));
+  }
+}
+
+class TripleImpl extends AbstractTriple {
+  private static final long serialVersionUID = -26504102803266709L;
+  TripleImpl(Node node, Node node2, Node node3) {
+    subjectNode = (SubjectNode)node;
+    predicateNode = (PredicateNode)node2;
+    objectNode = (ObjectNode)node3;
+  }
+}
+

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/StatementParser.java
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/StatementParser.java	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/StatementParser.java	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2010 Paul Gearon
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.content.rdfa;
+
+// Java 2 standard packages
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import javax.activation.MimeType;
+
+// Third party packages
+import org.apache.log4j.Logger;      // Apache Log4J
+import org.jrdf.graph.BlankNode;     // JRDF
+import org.jrdf.graph.Literal;
+import org.jrdf.graph.Node;
+import org.jrdf.graph.ObjectNode;
+import org.jrdf.graph.PredicateNode;
+import org.jrdf.graph.SubjectNode;
+import org.jrdf.graph.Triple;
+import org.xml.sax.InputSource;
+import org.xml.sax.XMLReader;
+
+import net.rootdev.javardfa.ParserFactory.Format;
+import net.rootdev.javardfa.StatementSink;
+import net.rootdev.javardfa.ParserFactory;
+
+
+// Locally written packages
+import org.mulgara.content.Content;
+import org.mulgara.content.NotModifiedException;
+import org.mulgara.parser.MulgaraParserException;
+import org.mulgara.query.TuplesException;
+import org.mulgara.query.rdf.BlankNodeImpl;
+import org.mulgara.query.rdf.LiteralImpl;
+import org.mulgara.query.rdf.TripleImpl;
+import org.mulgara.query.rdf.URIReferenceImpl;
+import org.mulgara.resolver.spi.ResolverSession;
+import org.mulgara.util.IntFile;
+import org.mulgara.util.TempDir;
+
+/**
+ *
+ * @created 2010-08-09
+ * @author Paul Gearon
+ */
+class StatementParser implements Runnable, StatementSink {
+
+  /** Logger. */
+  private static final Logger logger = Logger.getLogger(StatementParser.class.getName());
+
+  /** Text prefix for blank nodes. */
+  @SuppressWarnings("unused")
+  private static final String BLANK_PREFIX = "_:";
+
+  /** The prefix that rdfa-java uses */
+  private static final String RJ_PREFIX = "_:node";
+
+  /**
+   * Maximum size for the {@link #triples} buffer. Any larger and the parser will
+   * block and drain.
+   */
+  private static final long BUFFER_SIZE = 1000;
+
+  /** Mapping between parsed blank node IDs and local node numbers. */
+  private IntFile blankNodeIdMap;
+
+  /** Mapping between blank node IDs and blank-node instances that haven't been stored. */
+  private Map<Long,BlankNodeImpl> blankNodeInstMap = new HashMap<Long,BlankNodeImpl>();
+
+  /** The resolverSession to create new internal identifiers for blank nodes. */
+  private ResolverSession resolverSession;
+
+  /** The data to be parsed and its metadata */
+  private final Content content;
+
+  /** The stream containing the data to be parsed. */
+  private InputStream inputStream;
+
+  /** The parser for the input stream. */
+  private XMLReader reader;
+
+  /** The base of the document. */
+  private URI base;
+
+  /** Resolves relative URIs and IRIs to absolute URIs/IRIs */
+  private BasedResolver parseResolver;
+
+  /** The queue of triples generated by the parser. */
+  private LinkedList<Triple> triples = new LinkedList<Triple>();
+
+  /** The number of parsed statements */
+  private long statementCount = 0;
+
+  /** Indicates that parsing is complete */
+  private boolean finished = false;
+
+  /** Used to asynchronously indicate an exception. */
+  private Throwable exception = null;
+
+  /**
+   * Sets up the sink to start receiving triples.
+   * @param content Contains the data for parsing and its metadata.
+   * @param resolverSession Access to the database for inserting data.
+   */
+  StatementParser(Content content, ResolverSession resolverSession) throws NotModifiedException, TuplesException {
+    if (content == null) throw new IllegalArgumentException("Null \"content\" parameter");
+    if (resolverSession == null) throw new IllegalArgumentException("Null \"resolverSession\" parameter");
+
+    this.content = content;
+    this.resolverSession = resolverSession;
+    try {
+      this.blankNodeIdMap = IntFile.open(TempDir.createTempFile("rdfaidmap", null), true);
+      this.inputStream = content.newInputStream();
+      this.base = content.getURI();
+      parseResolver = new BasedResolver(content.getURIString());
+      reader = ParserFactory.createReaderForFormat(this, getType(content), parseResolver);
+    } catch (Exception e) {
+      throw new TuplesException("Unable to obtain input stream from " + content.getURI(), e);
+    }
+  }
+
+  /**
+   * @return the number of statements parsed so far
+   */
+  synchronized long getStatementCount() {
+    return statementCount;
+  }
+
+  /**
+   * @return the total number of statements in the file
+   */
+  synchronized long waitForStatementTotal() throws TuplesException {
+    while (!finished) {
+      checkForException();
+
+      // ignoring all incoming data
+      triples.clear();
+      blankNodeInstMap.clear();
+      notifyAll();
+
+      try {
+        wait();
+      } catch (InterruptedException ex) {
+        throw new TuplesException("Abort");
+      }
+    }
+    checkForException();
+    return statementCount;
+  }
+
+  public void run() {
+    Throwable t = null;
+
+    try {
+      reader.parse(new InputSource(inputStream));
+      if (logger.isDebugEnabled()) logger.debug("Parsed RDFa on " + content.getURI());
+      return;
+    } catch (Throwable th) {
+      th.printStackTrace();
+      t = th;
+    } finally {
+      synchronized (this) {
+        if (t != null) exception = t;
+        finished = true;
+        notifyAll();
+      }
+    }
+
+    if (logger.isDebugEnabled()) logger.debug("Exception while parsing RDFa", exception);
+  }
+
+  public void start() {
+    if (logger.isDebugEnabled()) logger.debug("Started RDFa document");
+  }
+
+  public void end() {
+    if (logger.isDebugEnabled()) logger.debug("End RDFa document");
+    finished = true;
+    synchronized (this) {
+      notifyAll();
+    }
+  }
+
+  public void addPrefix(String prefix, String uri) {
+    if (logger.isDebugEnabled()) logger.debug("@prefix " + prefix + ": <" + uri + "> .");
+  }
+
+  public void setBase(String base) {
+    try {
+      if (base != null) parseResolver.setBase(base);
+    } catch (IllegalArgumentException e) {
+      logger.warn("Invalid base in RDFa file: " + base);
+    }
+  }
+
+  /**
+   * Adds an triple with a Literal as the object.
+   * @param subject string form of the subject.
+   * @param predicate string form of the predicate.
+   * @param lex The lexical form of the literal in the object.
+   * @param lang The language code of the literal in the object. May be <code>null</code>.
+   * @param datatype The datatype of the literal in the object. May be <code>null</code>.
+   */
+  public void addLiteral(String subject, String predicate, String lex, String lang, String datatype) {
+    try {
+      enqueue((SubjectNode)toNode(subject), (PredicateNode)toNode(predicate), toLiteral(lex, lang, datatype));
+    } catch (MulgaraParserException e) {
+      logger.error("Unable to parse. " + e.getMessage());
+      return;
+    }
+  }
+
+
+  /**
+   * Adds an triple with a URI or blank node as the object.
+   * @param subject string form of the subject.
+   * @param predicate string form of the predicate.
+   * @param object string form of the object.
+   */
+  public void addObject(String subject, String predicate, String object) {
+    try {
+      enqueue((SubjectNode)toNode(subject), (PredicateNode)toNode(predicate), (ObjectNode)toNode(object));
+    } catch (MulgaraParserException e) {
+      logger.error("Unable to parse. " + e.getMessage());
+      return;
+    }
+  }
+
+
+  /**
+   * Add a parsed triple to the queue.
+   * @param subjectNode The subject of the triple.
+   * @param predicateNode The predicate of the triple.
+   * @param objectNode The object of the triple.
+   */
+  void enqueue(SubjectNode subjectNode, PredicateNode predicateNode, ObjectNode objectNode) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Parsed " + subjectNode + " " + predicateNode + " " + objectNode + " from " + content.getURI());
+    }
+
+    synchronized (this) {
+      // Wait for the triples buffer to drain if it's too full
+      while (triples.size() >= BUFFER_SIZE) {
+        try {
+          wait();
+        } catch (InterruptedException ex) {
+          throw new RuntimeException("Abort");
+        }
+      }
+
+      // Buffer the statement
+      triples.addLast(new TripleImpl(subjectNode, predicateNode, objectNode));
+      statementCount++;
+      notifyAll();
+    }
+  }
+
+  /**
+   * Convert and validate an AST object into a node.
+   *
+   * @param text The text of the node that was parsed.
+   * @return a {@link Node} formed from the text
+   * @throws MulgaraParserException An unhandled element was encountered.
+   */
+  private Node toNode(String text) throws MulgaraParserException {
+    if (text == null) return new URIReferenceImpl(base);
+
+    if (text.startsWith(RJ_PREFIX)) return getBlankNode(text);
+    return toUri(text);
+  }
+
+  /**
+   * Creates a URIReference out of a string.
+   * @param text The string to convert.
+   * @return A new URIReference containing the URI from the string.
+   * @throws MulgaraParserException The text was not a valid URI.
+   */
+  private Node toUri(String text) throws MulgaraParserException {
+    try {
+      return new URIReferenceImpl(new URI(text));
+    } catch (URISyntaxException e) {
+      throw new MulgaraParserException("Invalid URI: " + text, e);
+    }
+  }
+
+  /**
+   * Create a blank node from a URI with a blank node form.
+   *
+   * @param n The node to convert to an anonymous node.
+   * @return An anonymous node that the node maps to.
+   */
+  private BlankNode getBlankNode(String n) throws MulgaraParserException {
+    long anonId;
+    try {
+      anonId = Long.parseLong(n.substring(RJ_PREFIX.length()));
+    } catch (NumberFormatException nfe) {
+      throw new MulgaraParserException("Invalid blank node: " + n);
+    }
+    if (anonId < 0) throw new MulgaraParserException("Inexpected blank node format: " + n);
+
+    synchronized (this) {
+      // look up the id in the blank node map
+      long internalId = blankNodeIdMap.getLong(anonId);
+
+      // check if the node was found
+      BlankNodeImpl blankNode;
+      if (internalId == 0) {
+        blankNode = blankNodeInstMap.get(anonId);
+        if (blankNode == null) {
+          blankNode = new BlankNodeImpl();
+          blankNodeInstMap.put(anonId, blankNode);
+        }
+      } else {
+        // Found the ID, so need to recreate the anonymous resource for it
+        blankNode = new BlankNodeImpl(internalId);
+      }
+
+      return blankNode;
+    }
+  }
+
+  /**
+   * Creates a literal out of three components.
+   * @param text The lexical value of the literal.
+   * @param lang The language code of the literal, or <code>null</code> if not an
+   *        untyped literal with a language code.
+   * @param datatype The URI of the datatype of the literal, or <code>null</code>
+   *        if an untyped literal.
+   * @return A new literal.
+   */
+  Literal toLiteral(String text, String lang, String datatype) throws MulgaraParserException {
+    if (datatype != null) {
+      assert lang == null;
+      try {
+        return new LiteralImpl(text, new URI(datatype));
+      } catch (URISyntaxException e) {
+        throw new MulgaraParserException("Invalid datatype on literal: " + text + "^^" + datatype, e);
+      }
+    }
+    if (lang != null) return new LiteralImpl(text, lang);
+    return new LiteralImpl(text);
+  }
+
+  /**
+   * If an exception occurred in the parser, throws a TuplesException that
+   * wraps the exception.
+   */
+  private void checkForException() throws TuplesException {
+    if (exception != null) {
+      throw new TuplesException("Exception while reading " + content.getURIString(), exception);
+    }
+  }
+
+
+  /**
+   * Returns a new triple from the queue or null if there are no more triples.
+   * @return The oldest triple in the queue.
+   */
+  synchronized Triple getTriple() throws TuplesException {
+    while (triples.isEmpty()) {
+      checkForException();
+      if (finished) return null;
+
+      // Wait for more triples.
+      try {
+        wait();
+      } catch (InterruptedException ex) {
+        throw new TuplesException("Abort");
+      }
+    }
+    checkForException();
+    allocateBlankNodes();
+
+    notifyAll();
+    return triples.removeFirst();
+  }
+
+  /**
+   * Allocate the ids for the new blank nodes.
+   */
+  private synchronized void allocateBlankNodes() {
+    try {
+      for (Map.Entry<Long, BlankNodeImpl> entry : blankNodeInstMap.entrySet()) {
+        resolverSession.localize(entry.getValue());     // This sets and returns the node ID
+        blankNodeIdMap.putLong(entry.getKey(), entry.getValue().getNodeId());
+      }
+      blankNodeInstMap.clear();
+
+    } catch (Exception le) {
+      throw new RuntimeException("Unable to create blank node", le);
+    }
+  }
+
+  /**
+   * Stops the thread.
+   */
+  synchronized void terminate() {
+    Thread.currentThread().interrupt();
+    triples.clear();
+    notifyAll();
+  }
+
+  /**
+   * Tests if the parse is complete.
+   * @return <code>true</code> if parsing is over.
+   */
+  synchronized boolean isFinished() {
+    return finished;
+  }
+
+  /**
+   * Determine the type of parsing to be done, based on the content.
+   * @param c The Content to be parsed.
+   * @return Either <code>Format.XHTML</code> or <code>Format.HTML</code>.
+   * @throws NotModifiedException 
+   */
+  private Format getType(Content c) throws NotModifiedException {
+    MimeType t = c.getContentType();
+    if (RdfaContentHandler.XHTML_MIME.match(t)) return Format.XHTML;
+    if (RdfaContentHandler.HTML_MIME.match(t)) return Format.HTML;
+    logger.warn("Guessing HTML for unknown MIME type: " + t);
+    return Format.HTML;
+  }
+}

Added: trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/package.html
===================================================================
--- trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/package.html	                        (rev 0)
+++ trunk/src/jar/content-rdfa/java/org/mulgara/content/rdfa/package.html	2010-08-20 02:41:38 UTC (rev 1973)
@@ -0,0 +1,13 @@
+<html>
+<head>
+<title>RDFa Content Handler</title>
+</head>
+<body>
+<h1>
+RDFa content handler.
+</h1>
+<p>
+This package is a service provider for parsing HTML/XHTML documents with embedded RDFa data. It uses the java-rdfa library by Damian Steer. See: <a href="http://github.com/shellac/java-rdfa">http://github.com/shellac/java-rdfa</a>
+</p>
+</body>
+</html>



More information about the Mulgara-svn mailing list