1 package org
.argeo
.cms
.acr
;
3 import java
.util
.HashSet
;
4 import java
.util
.Locale
;
7 import java
.util
.concurrent
.CompletableFuture
;
8 import java
.util
.concurrent
.CompletionStage
;
9 import java
.util
.function
.Consumer
;
11 import javax
.security
.auth
.Subject
;
13 import org
.argeo
.api
.acr
.Content
;
14 import org
.argeo
.api
.acr
.ContentSession
;
15 import org
.argeo
.api
.acr
.CrName
;
16 import org
.argeo
.api
.acr
.DName
;
17 import org
.argeo
.api
.acr
.spi
.ContentProvider
;
18 import org
.argeo
.api
.acr
.spi
.ProvidedContent
;
19 import org
.argeo
.api
.acr
.spi
.ProvidedRepository
;
20 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
21 import org
.argeo
.api
.uuid
.UuidFactory
;
22 import org
.argeo
.cms
.acr
.xml
.DomContentProvider
;
24 /** Implements {@link ProvidedSession}. */
25 class CmsContentSession
implements ProvidedSession
{
26 final private AbstractContentRepository contentRepository
;
28 private final UUID uuid
;
29 private Subject subject
;
30 private Locale locale
;
32 private UuidFactory uuidFactory
;
34 private CompletableFuture
<ProvidedSession
> closed
= new CompletableFuture
<>();
36 private CompletableFuture
<ContentSession
> edition
;
38 private Set
<ContentProvider
> modifiedProviders
= new HashSet
<>();
40 private Content sessionRunDir
;
42 public CmsContentSession(AbstractContentRepository contentRepository
, UUID uuid
, Subject subject
, Locale locale
,
43 UuidFactory uuidFactory
) {
44 this.contentRepository
= contentRepository
;
45 this.subject
= subject
;
48 this.uuidFactory
= uuidFactory
;
52 closed
.complete(this);
54 if (sessionRunDir
!= null)
55 sessionRunDir
.remove();
59 public CompletionStage
<ProvidedSession
> onClose() {
60 return closed
.minimalCompletionStage();
64 public Content
get(String path
) {
65 if (!path
.startsWith(ContentUtils
.ROOT_SLASH
))
66 throw new IllegalArgumentException(path
+ " is not an absolute path");
67 ContentProvider contentProvider
= contentRepository
.getMountManager().findContentProvider(path
);
68 String mountPath
= contentProvider
.getMountPath();
69 String relativePath
= extractRelativePath(mountPath
, path
);
70 ProvidedContent content
= contentProvider
.get(CmsContentSession
.this, relativePath
);
75 public boolean exists(String path
) {
76 if (!path
.startsWith(ContentUtils
.ROOT_SLASH
))
77 throw new IllegalArgumentException(path
+ " is not an absolute path");
78 ContentProvider contentProvider
= contentRepository
.getMountManager().findContentProvider(path
);
79 String mountPath
= contentProvider
.getMountPath();
80 String relativePath
= extractRelativePath(mountPath
, path
);
81 return contentProvider
.exists(this, relativePath
);
84 private String
extractRelativePath(String mountPath
, String path
) {
85 String relativePath
= path
.substring(mountPath
.length());
86 if (relativePath
.length() > 0 && relativePath
.charAt(0) == '/')
87 relativePath
= relativePath
.substring(1);
92 public Subject
getSubject() {
97 public Locale
getLocale() {
102 public ProvidedRepository
getRepository() {
103 return contentRepository
;
106 public UuidFactory
getUuidFactory() {
114 public Content
getMountPoint(String path
) {
115 String
[] parent
= ContentUtils
.getParentPath(path
);
116 ProvidedContent mountParent
= (ProvidedContent
) get(parent
[0]);
117 // Content mountPoint = mountParent.getProvider().get(CmsContentSession.this, null, path);
118 return mountParent
.getMountPoint(parent
[1]);
126 // public String getNamespaceURI(String prefix) {
127 // return RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix);
128 //// return NamespaceUtils.getNamespaceURI((p) -> contentRepository.getTypesManager().getPrefixes().get(p), prefix);
132 // public Iterator<String> getPrefixes(String namespaceURI) {
133 // return RuntimeNamespaceContext.getNamespaceContext().getPrefixes(namespaceURI);
134 //// return NamespaceUtils.getPrefixes((ns) -> contentRepository.getTypesManager().getPrefixes().entrySet().stream()
135 //// .filter(e -> e.getValue().equals(ns)).map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet()),
140 public CompletionStage
<ContentSession
> edit(Consumer
<ContentSession
> work
) {
141 edition
= CompletableFuture
.supplyAsync(() -> {
144 }).thenApply((s
) -> {
145 synchronized (CmsContentSession
.this) {
147 for (ContentProvider provider
: modifiedProviders
) {
148 if (provider
instanceof DomContentProvider
) {
149 ((DomContentProvider
) provider
).persist(s
);
152 modifiedProviders
.clear();
156 return edition
.minimalCompletionStage();
160 public boolean isEditing() {
161 return edition
!= null && !edition
.isDone();
165 public synchronized void notifyModification(ProvidedContent content
) {
166 ContentProvider contentProvider
= content
.getProvider();
167 modifiedProviders
.add(contentProvider
);
171 public UUID
getUuid() {
176 public Content
getSessionRunDir() {
177 if (sessionRunDir
== null) {
178 String runDirPath
= CmsContentRepository
.RUN_BASE
+ '/' + uuid
.toString();
179 if (exists(runDirPath
))
180 sessionRunDir
= get(runDirPath
);
182 Content runDir
= get(CmsContentRepository
.RUN_BASE
);
183 // TODO deal with no run dir available?
184 sessionRunDir
= runDir
.add(uuid
.toString(),DName
.collection
.qName());
187 return sessionRunDir
;
191 // public String findNamespace(String prefix) {
192 // return prefixes.get(prefix);
196 // public Set<String> findPrefixes(String namespaceURI) {
197 // Set<String> res = prefixes.entrySet().stream().filter(e -> e.getValue().equals(namespaceURI))
198 // .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet());
204 // public String findPrefix(String namespaceURI) {
205 // if (CrName.CR_NAMESPACE_URI.equals(namespaceURI) && prefixes.containsKey(CrName.CR_DEFAULT_PREFIX))
206 // return CrName.CR_DEFAULT_PREFIX;
207 // return ProvidedSession.super.findPrefix(namespaceURI);