MARMOTTA-440: Continued alignment with w3c ldp working draft

Project: http://git-wip-us.apache.org/repos/asf/marmotta/repo
Commit: http://git-wip-us.apache.org/repos/asf/marmotta/commit/da1e8827
Tree: http://git-wip-us.apache.org/repos/asf/marmotta/tree/da1e8827
Diff: http://git-wip-us.apache.org/repos/asf/marmotta/diff/da1e8827

Branch: refs/heads/develop
Commit: da1e8827f78c8c0c24bd95f142146886a3e3df60
Parents: bb13208
Author: Jakob Frank <[email protected]>
Authored: Tue Mar 11 17:03:17 2014 +0100
Committer: Jakob Frank <[email protected]>
Committed: Tue Mar 11 17:03:17 2014 +0100

----------------------------------------------------------------------
 .../apache/marmotta/commons/vocabulary/LDP.java |  31 ++----
 .../platform/ldp/api/LdpBinaryStoreService.java |   3 +
 .../marmotta/platform/ldp/api/LdpService.java   |  11 ++
 .../ldp/services/LdpBinaryStoreServiceImpl.java |  16 +++
 .../platform/ldp/services/LdpServiceImpl.java   | 106 ++++++++++++++-----
 .../platform/ldp/webservices/LdpWebService.java |  50 +++++++--
 6 files changed, 158 insertions(+), 59 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/commons/marmotta-sesame-tools/marmotta-model-vocabs/src/main/java/org/apache/marmotta/commons/vocabulary/LDP.java
----------------------------------------------------------------------
diff --git 
a/commons/marmotta-sesame-tools/marmotta-model-vocabs/src/main/java/org/apache/marmotta/commons/vocabulary/LDP.java
 
b/commons/marmotta-sesame-tools/marmotta-model-vocabs/src/main/java/org/apache/marmotta/commons/vocabulary/LDP.java
index 7357b96..aa17814 100644
--- 
a/commons/marmotta-sesame-tools/marmotta-model-vocabs/src/main/java/org/apache/marmotta/commons/vocabulary/LDP.java
+++ 
b/commons/marmotta-sesame-tools/marmotta-model-vocabs/src/main/java/org/apache/marmotta/commons/vocabulary/LDP.java
@@ -30,17 +30,9 @@ public class LDP {
     public static final String PREFIX = "ldp";
 
     /**
-     * A Linked Data Platform Container (LDPC) that also conforms to
-     * additional patterns and conventions for managing members.  It is 
distinguished from
-     * CompositeContainer by the following behaviors:
-     * <ol>
-     * <li>Clients cannot assume that an AggregateContainer, when deleted, 
deletes its members.
-     * </ol>
-     * <p/>
-     * While every attempt is made to be complete in this list, readers should 
also refer
-     * to the specification defining this ontology.
+     * FIXME: Not yet part of the official vocab, but used in the Spec. 
(2014-03-11)
      */
-    public static final URI AggregateContainer;
+    public static final URI DirectContainer;
 
     /**
      * FIXME: Not yet part of the official vocab, but used in the Spec. 
(2014-02-18)
@@ -48,17 +40,9 @@ public class LDP {
     public static final URI BasicContainer;
 
     /**
-     * A Linked Data Platform Container (LDPC) that also conforms to
-     * additional patterns and conventions for managing members.  It is 
distinguished from
-     * AggregateContainer by the following behaviors:
-     * <ol>
-     * <li>An CompositeContainer, when deleted, must delete all its members.
-     * </ol>
-     * <p/>
-     * While every attempt is made to be complete in this list, readers should 
also
-     * refer to the specification defining this ontology.
+     * FIXME: Not yet part of the official vocab, but used in the Spec. 
(2014-03-11)
      */
-    public static final URI CompositeContainer;
+    public static final URI IndirectContainer;
 
     /**
      * A Linked Data Platform Resource (LDPR) that also conforms to
@@ -86,6 +70,7 @@ public class LDP {
 
     /**
      * A HTTP-addressable resource with a Non-RDF Source representation.
+     * FIXME: Not yet part of the vocab, but used in the spec. (2014-03-11)
      */
     public static final URI NonRdfResource;
 
@@ -127,9 +112,9 @@ public class LDP {
 
     static {
         ValueFactory factory = ValueFactoryImpl.getInstance();
-        AggregateContainer = factory.createURI(LDP.NAMESPACE, 
"AggregateContainer");
-        BasicContainer = factory.createURI(LDP.NAMESPACE, "BasicContainer");
-        CompositeContainer = factory.createURI(LDP.NAMESPACE, 
"CompositeContainer");
+        DirectContainer = factory.createURI(LDP.NAMESPACE, "DirectContainer"); 
//TODO: missing term in the vocab
+        BasicContainer = factory.createURI(LDP.NAMESPACE, "BasicContainer"); 
//TODO: missing term in the vocab
+        IndirectContainer = factory.createURI(LDP.NAMESPACE, 
"IndirectContainer"); //TODO: missing term in the vocab
         Container = factory.createURI(LDP.NAMESPACE, "Container");
         Page = factory.createURI(LDP.NAMESPACE, "Page");
         Resource = factory.createURI(LDP.NAMESPACE, "Resource");

http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java
 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java
index 34ec302..6e8f46a 100644
--- 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java
+++ 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpBinaryStoreService.java
@@ -38,4 +38,7 @@ public interface LdpBinaryStoreService {
 
     InputStream read(URI resource) throws IOException;
 
+    String getHash(String resource);
+
+    String getHash(URI uri);
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
index f998028..4795512 100644
--- 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
+++ 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/api/LdpService.java
@@ -111,7 +111,18 @@ public interface LdpService {
 
     String getMimeType(RepositoryConnection connection, URI uri) throws 
RepositoryException;
 
+    boolean isNonRdfSourceResource(RepositoryConnection connection, String 
resource) throws RepositoryException;
+
+    boolean isNonRdfSourceResource(RepositoryConnection connection, URI uri) 
throws RepositoryException;
+
     URI getRdfSourceForNonRdfSource(RepositoryConnection connection, URI uri) 
throws RepositoryException;
 
     URI getRdfSourceForNonRdfSource(RepositoryConnection connection, String 
resource) throws RepositoryException;
+
+    boolean isRdfSourceResource(RepositoryConnection connection, String 
resource) throws RepositoryException;
+
+    boolean isRdfSourceResource(RepositoryConnection connection, URI uri) 
throws RepositoryException;
+
+    URI getNonRdfSourceForRdfSource(RepositoryConnection connection, String 
resource) throws RepositoryException;
+    URI getNonRdfSourceForRdfSource(RepositoryConnection connection, URI uri) 
throws RepositoryException;
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java
 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java
index 01a305f..09f34c6 100644
--- 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java
+++ 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpBinaryStoreServiceImpl.java
@@ -19,6 +19,7 @@ package org.apache.marmotta.platform.ldp.services;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
+import org.apache.marmotta.commons.util.HashUtils;
 import org.apache.marmotta.platform.core.api.config.ConfigurationService;
 import org.apache.marmotta.platform.core.events.ConfigurationChangedEvent;
 import org.apache.marmotta.platform.core.events.SystemStartupEvent;
@@ -113,4 +114,19 @@ public class LdpBinaryStoreServiceImpl implements 
LdpBinaryStoreService {
         return read(resource.stringValue());
     }
 
+
+    @Override
+    public String getHash(String resource) {
+        try(InputStream is = Files.newInputStream(getFile(resource))) {
+            return HashUtils.md5sum(is);
+        } catch (URISyntaxException | IOException e) {
+            log.error("Error calculating file-md5 of {}: {}", resource, e);
+            return null;
+        }
+    }
+
+    @Override
+    public String getHash(URI uri) {
+        return getHash(uri.stringValue());
+    }
 }

http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
index 4818d19..54350d4 100644
--- 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
+++ 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/services/LdpServiceImpl.java
@@ -101,18 +101,38 @@ public class LdpServiceImpl implements LdpService {
 
     @Override
     public List<Statement> getLdpTypes(RepositoryConnection connection, URI 
resource) throws RepositoryException {
-            return Iterations.asList(new FilterIteration<Statement, 
RepositoryException>(connection.getStatements(resource, RDF.TYPE, null, false, 
ldpContext)) {
-                @Override
-                protected boolean accept(Statement statement) {
-                    final Value object = statement.getObject();
-                    return object instanceof URI && 
object.stringValue().startsWith(LDP.NAMESPACE);
-                }
-            }); //FIXME
+        return Iterations.asList(new FilterIteration<Statement, 
RepositoryException>(connection.getStatements(resource, RDF.TYPE, null, false, 
ldpContext)) {
+            @Override
+            protected boolean accept(Statement statement) {
+                final Value object = statement.getObject();
+                return object instanceof URI && 
object.stringValue().startsWith(LDP.NAMESPACE);
+            }
+        }); //FIXME
+    }
+
+    @Override
+    public boolean isRdfSourceResource(RepositoryConnection connection, String 
resource) throws RepositoryException {
+        return isRdfSourceResource(connection, buildURI(resource));
+    }
+
+    @Override
+    public boolean isRdfSourceResource(RepositoryConnection connection, URI 
uri) throws RepositoryException {
+        return connection.hasStatement(uri, RDF.TYPE, LDP.RDFSource, true, 
ldpContext);
+    }
+
+    @Override
+    public boolean isNonRdfSourceResource(RepositoryConnection connection, 
String resource) throws RepositoryException {
+        return isRdfSourceResource(connection, buildURI(resource));
+    }
+
+    @Override
+    public boolean isNonRdfSourceResource(RepositoryConnection connection, URI 
uri) throws RepositoryException {
+        return connection.hasStatement(uri, RDF.TYPE, LDP.NonRdfResource, 
true, ldpContext);
     }
 
+
     @Override
     public URI getRdfSourceForNonRdfSource(final RepositoryConnection 
connection, URI uri) throws RepositoryException {
-        // FIXME: someone should double check this (jakob)
         final FilterIteration<Statement, RepositoryException> it =
                 new FilterIteration<Statement, 
RepositoryException>(connection.getStatements(uri, DCTERMS.isFormatOf, null, 
true, ldpContext)) {
                     @Override
@@ -138,6 +158,32 @@ public class LdpServiceImpl implements LdpService {
     }
 
     @Override
+    public URI getNonRdfSourceForRdfSource(RepositoryConnection connection, 
String resource) throws RepositoryException {
+        return getNonRdfSourceForRdfSource(connection, buildURI(resource));
+    }
+
+    @Override
+    public URI getNonRdfSourceForRdfSource(final RepositoryConnection 
connection, URI uri) throws RepositoryException {
+        final FilterIteration<Statement, RepositoryException> it =
+                new FilterIteration<Statement, 
RepositoryException>(connection.getStatements(uri, DCTERMS.hasFormat, null, 
true, ldpContext)) {
+                    @Override
+                    protected boolean accept(Statement statement) throws 
RepositoryException {
+                        return statement.getObject() instanceof URI
+                                && connection.hasStatement((URI) 
statement.getObject(), RDF.TYPE, LDP.NonRdfResource, true, ldpContext);
+                    }
+                };
+        try {
+            if (it.hasNext()) {
+                return (URI) it.next().getObject();
+            } else {
+                return null;
+            }
+        }finally {
+            it.close();
+        }
+    }
+
+    @Override
     public void exportResource(RepositoryConnection connection, String 
resource, OutputStream output, RDFFormat format) throws RepositoryException, 
RDFHandlerException {
         exportResource(connection, buildURI(resource), output, format);
     }
@@ -209,6 +255,7 @@ public class LdpServiceImpl implements LdpService {
         if (hasType(connection, container, LDP.BasicContainer)) {
             connection.remove(container, DCTERMS.modified, null, ldpContext);
         } else {
+            connection.add(container, RDF.TYPE, LDP.Container, ldpContext);
             connection.add(container, RDF.TYPE, LDP.BasicContainer, 
ldpContext);
         }
 
@@ -260,26 +307,35 @@ public class LdpServiceImpl implements LdpService {
 
     @Override
     public EntityTag generateETag(RepositoryConnection connection, URI uri) 
throws RepositoryException {
-        final RepositoryResult<Statement> stmts = 
connection.getStatements(uri, DCTERMS.modified, null, true, ldpContext);
-        try {
-            // TODO: ETag is the last-modified date (explicitly managed) thus 
only weak.
-            Date latest = null;
-            while (stmts.hasNext()) {
-                Value o = stmts.next().getObject();
-                if (o instanceof Literal) {
-                    Date d = 
((Literal)o).calendarValue().toGregorianCalendar().getTime();
-                    if (latest == null || d.after(latest)) {
-                        latest = d;
-                    }
-                }
-            }
-            if (latest != null) {
-                return new EntityTag(String.valueOf(latest.getTime()), true);
+        if (isNonRdfSourceResource(connection, uri)) {
+            final String hash = binaryStore.getHash(uri.stringValue());
+            if (hash != null) {
+                return new EntityTag(hash, false);
             } else {
                 return null;
             }
-        } finally {
-            stmts.close();
+        } else {
+            final RepositoryResult<Statement> stmts = 
connection.getStatements(uri, DCTERMS.modified, null, true, ldpContext);
+            try {
+                // TODO: ETag is the last-modified date (explicitly managed) 
thus only weak.
+                Date latest = null;
+                while (stmts.hasNext()) {
+                    Value o = stmts.next().getObject();
+                    if (o instanceof Literal) {
+                        Date d = 
((Literal)o).calendarValue().toGregorianCalendar().getTime();
+                        if (latest == null || d.after(latest)) {
+                            latest = d;
+                        }
+                    }
+                }
+                if (latest != null) {
+                    return new EntityTag(String.valueOf(latest.getTime()), 
true);
+                } else {
+                    return null;
+                }
+            } finally {
+                stmts.close();
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/marmotta/blob/da1e8827/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
----------------------------------------------------------------------
diff --git 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
index c4f68d3..8bf49b4 100644
--- 
a/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
+++ 
b/platform/marmotta-ldp/src/main/java/org/apache/marmotta/platform/ldp/webservices/LdpWebService.java
@@ -110,7 +110,17 @@ public class LdpWebService {
 
             // TODO: Proper content negotiation
 
-            final RDFFormat format = 
Rio.getWriterFormatForMIMEType(type.toString());
+            final RDFFormat format;
+            if (type.isWildcardType()) { // No explicit Accept Header
+                if (ldpService.isRdfSourceResource(conn, resource)) {
+                    format = RDFFormat.TURTLE;
+                } else {
+                    format = null;
+                }
+            } else {
+                format = 
Rio.getWriterFormatForMIMEType(LdpUtils.getMimeType(type), null);
+            }
+
             if (format == null) {
                 log.debug("GET to <{}> with non-RDF format {}, so looking for 
a LDP-BR", resource, type);
                 final StreamingOutput entity = new StreamingOutput() {
@@ -208,6 +218,13 @@ public class LdpWebService {
 
             conn.begin();
 
+            if (ldpService.isNonRdfSourceResource(conn, container)) {
+                log.info("POSTing to a NonRdfSource is not allowed ({})", 
container);
+                final Response.ResponseBuilder response = createResponse(conn, 
Response.Status.METHOD_NOT_ALLOWED, container).entity("POST to NonRdfSource is 
not allowed\n");
+                conn.commit();
+                return response.build();
+            }
+
             log.trace("Checking possible name clash for new resource <{}>", 
newResource);
             if (ldpService.exists(conn, newResource)) {
                 int i = 0;
@@ -229,7 +246,7 @@ public class LdpWebService {
                 String location = ldpService.addResource(conn, container, 
newResource, mimeType, postBody);
                 final Response.ResponseBuilder response = createResponse(conn, 
Response.Status.CREATED, container).location(java.net.URI.create(location));
                 if (newResource.compareTo(location) != 0) {
-                    response.link(newResource, "describedby"); //FIXME: Sec. 
6.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15
+                    response.link(newResource, "describedby"); //FIXME: Sec. 
5.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15
                 }
                 conn.commit();
                 return response.build();
@@ -414,14 +431,18 @@ public class LdpWebService {
 
             Response.ResponseBuilder builder = createResponse(con, 
Response.Status.OK, resource);
 
-            // Sec. 4.2.8.2
-            builder.allow("GET", "HEAD", "POST", "PATCH", "OPTIONS");
-
-            // Sec. 4.2.3 / Sec. ??
-            builder.header("Accept-Post", "text/turtle, */*");
-
-            // Sec. 4.2.7.1
-            builder.header("Accept-Patch", RdfPatchParser.MIME_TYPE);
+            if (ldpService.isNonRdfSourceResource(con, resource)) {
+                // Sec. 4.2.8.2
+                builder.allow("GET", "HEAD", "OPTIONS");
+            } else if (ldpService.isRdfSourceResource(con, resource)) {
+                // Sec. 4.2.8.2
+                builder.allow("GET", "HEAD", "POST", "PATCH", "OPTIONS");
+                // Sec. 4.2.3 / Sec. ??
+                // TODO: LDP Interaction Model!
+                builder.header("Accept-Post", "text/turtle, */*");
+                // Sec. 4.2.7.1
+                builder.header("Accept-Patch", RdfPatchParser.MIME_TYPE);
+            }
 
             con.commit();
             return builder.build();
@@ -469,7 +490,14 @@ public class LdpWebService {
 
             final URI rdfSource = 
ldpService.getRdfSourceForNonRdfSource(connection, resource);
             if (rdfSource != null) {
-                rb.link(rdfSource.stringValue(), "describedby"); //FIXME: Sec. 
6.2.3.12, see also http://www.w3.org/2012/ldp/track/issues/15
+                // FIXME: Sec. 5.2.3.12, see also 
http://www.w3.org/2012/ldp/track/issues/15
+                rb.link(rdfSource.stringValue(), "meta");
+                rb.link(rdfSource.stringValue(), "describedby");
+            }
+            final URI nonRdfSource = 
ldpService.getNonRdfSourceForRdfSource(connection, resource);
+            if (nonRdfSource != null) {
+                // TODO: Propose to LDP-WG?
+                rb.link(nonRdfSource.stringValue(), "content");
             }
 
             // ETag (Sec. 5.2.7)

Reply via email to