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
.DName
;
16 import org
.argeo
.api
.acr
.spi
.ContentProvider
;
17 import org
.argeo
.api
.acr
.spi
.ProvidedContent
;
18 import org
.argeo
.api
.acr
.spi
.ProvidedRepository
;
19 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
20 import org
.argeo
.api
.uuid
.UuidFactory
;
21 import org
.argeo
.cms
.acr
.xml
.DomContentProvider
;
23 /** Implements {@link ProvidedSession}. */
24 class CmsContentSession
implements ProvidedSession
{
25 final private AbstractContentRepository contentRepository
;
27 private final UUID uuid
;
28 private Subject subject
;
29 private Locale locale
;
31 private UuidFactory uuidFactory
;
33 private CompletableFuture
<ProvidedSession
> closed
= new CompletableFuture
<>();
35 private CompletableFuture
<ContentSession
> edition
;
37 private Set
<ContentProvider
> modifiedProviders
= new HashSet
<>();
39 private Content sessionRunDir
;
41 public CmsContentSession(AbstractContentRepository contentRepository
, UUID uuid
, Subject subject
, Locale locale
,
42 UuidFactory uuidFactory
) {
43 this.contentRepository
= contentRepository
;
44 this.subject
= subject
;
47 this.uuidFactory
= uuidFactory
;
51 closed
.complete(this);
53 if (sessionRunDir
!= null)
54 sessionRunDir
.remove();
58 public CompletionStage
<ProvidedSession
> onClose() {
59 return closed
.minimalCompletionStage();
63 public Content
get(String path
) {
64 if (!path
.startsWith(ContentUtils
.ROOT_SLASH
))
65 throw new IllegalArgumentException(path
+ " is not an absolute path");
66 ContentProvider contentProvider
= contentRepository
.getMountManager().findContentProvider(path
);
67 String mountPath
= contentProvider
.getMountPath();
68 String relativePath
= extractRelativePath(mountPath
, path
);
69 ProvidedContent content
= contentProvider
.get(CmsContentSession
.this, relativePath
);
74 public boolean exists(String path
) {
75 if (!path
.startsWith(ContentUtils
.ROOT_SLASH
))
76 throw new IllegalArgumentException(path
+ " is not an absolute path");
77 ContentProvider contentProvider
= contentRepository
.getMountManager().findContentProvider(path
);
78 String mountPath
= contentProvider
.getMountPath();
79 String relativePath
= extractRelativePath(mountPath
, path
);
80 return contentProvider
.exists(this, relativePath
);
83 private String
extractRelativePath(String mountPath
, String path
) {
84 String relativePath
= path
.substring(mountPath
.length());
85 if (relativePath
.length() > 0 && relativePath
.charAt(0) == '/')
86 relativePath
= relativePath
.substring(1);
91 public Subject
getSubject() {
96 public Locale
getLocale() {
101 public ProvidedRepository
getRepository() {
102 return contentRepository
;
105 public UuidFactory
getUuidFactory() {
113 public Content
getMountPoint(String path
) {
114 String
[] parent
= ContentUtils
.getParentPath(path
);
115 ProvidedContent mountParent
= (ProvidedContent
) get(parent
[0]);
116 // Content mountPoint = mountParent.getProvider().get(CmsContentSession.this, null, path);
117 return mountParent
.getMountPoint(parent
[1]);
124 public CompletionStage
<ContentSession
> edit(Consumer
<ContentSession
> work
) {
125 edition
= CompletableFuture
.supplyAsync(() -> {
128 }).thenApply((s
) -> {
129 synchronized (CmsContentSession
.this) {
131 for (ContentProvider provider
: modifiedProviders
) {
132 if (provider
instanceof DomContentProvider
) {
133 ((DomContentProvider
) provider
).persist(s
);
136 modifiedProviders
.clear();
140 return edition
.minimalCompletionStage();
144 public boolean isEditing() {
145 return edition
!= null && !edition
.isDone();
149 public synchronized void notifyModification(ProvidedContent content
) {
150 ContentProvider contentProvider
= content
.getProvider();
151 modifiedProviders
.add(contentProvider
);
155 public UUID
getUuid() {
160 public Content
getSessionRunDir() {
161 if (sessionRunDir
== null) {
162 String runDirPath
= CmsContentRepository
.RUN_BASE
+ '/' + uuid
.toString();
163 if (exists(runDirPath
))
164 sessionRunDir
= get(runDirPath
);
166 Content runDir
= get(CmsContentRepository
.RUN_BASE
);
167 // TODO deal with no run dir available?
168 sessionRunDir
= runDir
.add(uuid
.toString(), DName
.collection
.qName());
171 return sessionRunDir
;
175 // public String findNamespace(String prefix) {
176 // return prefixes.get(prefix);
180 // public Set<String> findPrefixes(String namespaceURI) {
181 // Set<String> res = prefixes.entrySet().stream().filter(e -> e.getValue().equals(namespaceURI))
182 // .map(Map.Entry::getKey).collect(Collectors.toUnmodifiableSet());
188 // public String findPrefix(String namespaceURI) {
189 // if (CrName.CR_NAMESPACE_URI.equals(namespaceURI) && prefixes.containsKey(CrName.CR_DEFAULT_PREFIX))
190 // return CrName.CR_DEFAULT_PREFIX;
191 // return ProvidedSession.super.findPrefix(namespaceURI);