Introduce namespace support
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / gcr / fs / FsContent.java
index 62ae613f0f737b4c71befa8bee527daf1f59e9d9..5efa65959b50a86affbf5e0b3e0b5bcc246c339d 100644 (file)
@@ -8,41 +8,62 @@ import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
 import java.nio.file.attribute.UserDefinedFileAttributeView;
 import java.time.Instant;
-import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Map;
 import java.util.Set;
 
+import javax.xml.namespace.QName;
+
 import org.argeo.api.gcr.Content;
+import org.argeo.api.gcr.ContentName;
 import org.argeo.api.gcr.ContentResourceException;
 import org.argeo.api.gcr.CrName;
-import org.argeo.api.gcr.ContentName;
 import org.argeo.api.gcr.spi.AbstractContent;
+import org.argeo.api.gcr.spi.ProvidedContent;
+import org.argeo.api.gcr.spi.ProvidedSession;
 import org.argeo.util.FsUtils;
 
-public class FsContent extends AbstractContent implements Content {
+public class FsContent extends AbstractContent implements ProvidedContent {
        private final static String USER_ = "user:";
 
-       private static final Set<String> BASIC_KEYS = new HashSet<>(
-                       Arrays.asList("basic:creationTime", "basic:lastModifiedTime", "basic:size", "basic:fileKey"));
-       private static final Set<String> POSIX_KEYS;
+       private static final Map<QName, String> BASIC_KEYS;
+       private static final Map<QName, String> POSIX_KEYS;
        static {
-               POSIX_KEYS = new HashSet<>(BASIC_KEYS);
-               POSIX_KEYS.add("owner:owner");
-               POSIX_KEYS.add("posix:group");
-               POSIX_KEYS.add("posix:permissions");
+               BASIC_KEYS = new HashMap<>();
+               BASIC_KEYS.put(CrName.CREATION_TIME.get(), "basic:creationTime");
+               BASIC_KEYS.put(CrName.LAST_MODIFIED_TIME.get(), "basic:lastModifiedTime");
+               BASIC_KEYS.put(CrName.SIZE.get(), "basic:size");
+               BASIC_KEYS.put(CrName.FILE_KEY.get(), "basic:fileKey");
+
+               POSIX_KEYS = new HashMap<>(BASIC_KEYS);
+               POSIX_KEYS.put(CrName.OWNER.get(), "owner:owner");
+               POSIX_KEYS.put(CrName.GROUP.get(), "posix:group");
+               POSIX_KEYS.put(CrName.PERMISSIONS.get(), "posix:permissions");
        }
 
-       private final FsContentProvider contentProvider;
+       private final ProvidedSession session;
+       private final FsContentProvider provider;
        private final Path path;
        private final boolean isRoot;
+       private final QName name;
 
-       public FsContent(FsContentProvider contentProvider, Path path) {
-               super();
-               this.contentProvider = contentProvider;
+       protected FsContent(ProvidedSession session, FsContentProvider contentProvider, Path path) {
+               this.session = session;
+               this.provider = contentProvider;
                this.path = path;
                this.isRoot = contentProvider.isRoot(path);
+               // TODO check file names with ':' ?
+               if (isRoot)
+                       this.name = CrName.ROOT.get();
+               else
+                       this.name = session.parsePrefixedName(path.getFileName().toString());
+       }
+
+       protected FsContent(FsContent context, Path path) {
+               this(context.getSession(), context.getProvider(), path);
        }
 
        private boolean isPosix() {
@@ -50,10 +71,8 @@ public class FsContent extends AbstractContent implements Content {
        }
 
        @Override
-       public String getName() {
-               if (isRoot)
-                       return "";
-               return path.getFileName().toString();
+       public QName getName() {
+               return name;
        }
 
        /*
@@ -61,7 +80,7 @@ public class FsContent extends AbstractContent implements Content {
         */
 
        @Override
-       public <A> A get(String key, Class<A> clss) {
+       public <A> A get(QName key, Class<A> clss) {
                Object value;
                try {
                        // We need to add user: when accessing via Files#getAttribute
@@ -85,13 +104,13 @@ public class FsContent extends AbstractContent implements Content {
        }
 
        @Override
-       protected Iterable<String> keys() {
-               Set<String> result = new HashSet<>(isPosix() ? POSIX_KEYS : BASIC_KEYS);
+       protected Iterable<QName> keys() {
+               Set<QName> result = new HashSet<>(isPosix() ? POSIX_KEYS.keySet() : BASIC_KEYS.keySet());
                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
                if (udfav != null) {
                        try {
                                for (String name : udfav.list()) {
-                                       result.add(name);
+                                       result.add(session.parsePrefixedName(name));
                                }
                        } catch (IOException e) {
                                throw new ContentResourceException("Cannot list attributes for " + path, e);
@@ -101,33 +120,33 @@ public class FsContent extends AbstractContent implements Content {
        }
 
        @Override
-       protected void removeAttr(String key) {
+       protected void removeAttr(QName key) {
                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
                try {
-                       udfav.delete(key);
+                       udfav.delete(session.toPrefixedName(key));
                } catch (IOException e) {
                        throw new ContentResourceException("Cannot delete attribute " + key + " for " + path, e);
                }
        }
 
        @Override
-       public Object put(String key, Object value) {
+       public Object put(QName key, Object value) {
                Object previous = get(key);
                UserDefinedFileAttributeView udfav = Files.getFileAttributeView(path, UserDefinedFileAttributeView.class);
                ByteBuffer bb = ByteBuffer.wrap(value.toString().getBytes(StandardCharsets.UTF_8));
                try {
-                       int size = udfav.write(key, bb);
+                       int size = udfav.write(session.toPrefixedName(key), bb);
                } catch (IOException e) {
                        throw new ContentResourceException("Cannot delete attribute " + key + " for " + path, e);
                }
                return previous;
        }
 
-       protected String toFsAttributeKey(String key) {
-               if (POSIX_KEYS.contains(key))
-                       return key;
+       protected String toFsAttributeKey(QName key) {
+               if (POSIX_KEYS.containsKey(key))
+                       return POSIX_KEYS.get(key);
                else
-                       return USER_ + key;
+                       return USER_ + session.toPrefixedName(key);
        }
 
        /*
@@ -137,7 +156,7 @@ public class FsContent extends AbstractContent implements Content {
        public Iterator<Content> iterator() {
                if (Files.isDirectory(path)) {
                        try {
-                               return Files.list(path).map((p) -> (Content) new FsContent(contentProvider, p)).iterator();
+                               return Files.list(path).map((p) -> (Content) new FsContent(this, p)).iterator();
                        } catch (IOException e) {
                                throw new ContentResourceException("Cannot list " + path, e);
                        }
@@ -147,10 +166,10 @@ public class FsContent extends AbstractContent implements Content {
        }
 
        @Override
-       public Content add(String name, ContentName... classes) {
+       public Content add(QName name, QName... classes) {
                try {
-                       Path newPath = path.resolve(name);
-                       if (ContentName.contains(classes, CrName.COLLECTION))
+                       Path newPath = path.resolve(session.toPrefixedName(name));
+                       if (ContentName.contains(classes, CrName.COLLECTION.get()))
                                Files.createDirectory(newPath);
                        else
                                Files.createFile(newPath);
@@ -158,7 +177,7 @@ public class FsContent extends AbstractContent implements Content {
 //             for(ContentClass clss:classes) {
 //                     Files.setAttribute(newPath, name, newPath, null)
 //             }
-                       return new FsContent(contentProvider, newPath);
+                       return new FsContent(this, newPath);
                } catch (IOException e) {
                        throw new ContentResourceException("Cannot create new content", e);
                }
@@ -173,7 +192,20 @@ public class FsContent extends AbstractContent implements Content {
        public Content getParent() {
                if (isRoot)
                        return null;// TODO deal with mounts
-               return new FsContent(contentProvider, path.getParent());
+               return new FsContent(this, path.getParent());
+       }
+
+       /*
+        * ACCESSORS
+        */
+       @Override
+       public ProvidedSession getSession() {
+               return session;
+       }
+
+       @Override
+       public FsContentProvider getProvider() {
+               return provider;
        }
 
 }