]> git.argeo.org Git - lgpl/argeo-commons.git/blob - acr/CmsContentSession.java
Prepare next development cycle
[lgpl/argeo-commons.git] / acr / CmsContentSession.java
1 package org.argeo.cms.acr;
2
3 import java.util.HashSet;
4 import java.util.Locale;
5 import java.util.Set;
6 import java.util.UUID;
7 import java.util.concurrent.CompletableFuture;
8 import java.util.concurrent.CompletionStage;
9 import java.util.function.Consumer;
10
11 import javax.security.auth.Subject;
12
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;
23
24 /** Implements {@link ProvidedSession}. */
25 class CmsContentSession implements ProvidedSession {
26 final private AbstractContentRepository contentRepository;
27
28 private final UUID uuid;
29 private Subject subject;
30 private Locale locale;
31
32 private UuidFactory uuidFactory;
33
34 private CompletableFuture<ProvidedSession> closed = new CompletableFuture<>();
35
36 private CompletableFuture<ContentSession> edition;
37
38 private Set<ContentProvider> modifiedProviders = new HashSet<>();
39
40 private Content sessionRunDir;
41
42 public CmsContentSession(AbstractContentRepository contentRepository, UUID uuid, Subject subject, Locale locale,
43 UuidFactory uuidFactory) {
44 this.contentRepository = contentRepository;
45 this.subject = subject;
46 this.locale = locale;
47 this.uuid = uuid;
48 this.uuidFactory = uuidFactory;
49 }
50
51 public void close() {
52 closed.complete(this);
53
54 if (sessionRunDir != null)
55 sessionRunDir.remove();
56 }
57
58 @Override
59 public CompletionStage<ProvidedSession> onClose() {
60 return closed.minimalCompletionStage();
61 }
62
63 @Override
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);
71 return content;
72 }
73
74 @Override
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);
82 }
83
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);
88 return relativePath;
89 }
90
91 @Override
92 public Subject getSubject() {
93 return subject;
94 }
95
96 @Override
97 public Locale getLocale() {
98 return locale;
99 }
100
101 @Override
102 public ProvidedRepository getRepository() {
103 return contentRepository;
104 }
105
106 public UuidFactory getUuidFactory() {
107 return uuidFactory;
108 }
109
110 /*
111 * MOUNT MANAGEMENT
112 */
113 @Override
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]);
119 }
120
121 /*
122 * NAMESPACE CONTEXT
123 */
124
125 // @Override
126 // public String getNamespaceURI(String prefix) {
127 // return RuntimeNamespaceContext.getNamespaceContext().getNamespaceURI(prefix);
128 //// return NamespaceUtils.getNamespaceURI((p) -> contentRepository.getTypesManager().getPrefixes().get(p), prefix);
129 // }
130 //
131 // @Override
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()),
136 //// namespaceURI);
137 // }
138
139 @Override
140 public CompletionStage<ContentSession> edit(Consumer<ContentSession> work) {
141 edition = CompletableFuture.supplyAsync(() -> {
142 work.accept(this);
143 return this;
144 }).thenApply((s) -> {
145 synchronized (CmsContentSession.this) {
146 // TODO optimise
147 for (ContentProvider provider : modifiedProviders) {
148 if (provider instanceof DomContentProvider) {
149 ((DomContentProvider) provider).persist(s);
150 }
151 }
152 modifiedProviders.clear();
153 return s;
154 }
155 });
156 return edition.minimalCompletionStage();
157 }
158
159 @Override
160 public boolean isEditing() {
161 return edition != null && !edition.isDone();
162 }
163
164 @Override
165 public synchronized void notifyModification(ProvidedContent content) {
166 ContentProvider contentProvider = content.getProvider();
167 modifiedProviders.add(contentProvider);
168 }
169
170 @Override
171 public UUID getUuid() {
172 return uuid;
173 }
174
175 @Override
176 public Content getSessionRunDir() {
177 if (sessionRunDir == null) {
178 String runDirPath = CmsContentRepository.RUN_BASE + '/' + uuid.toString();
179 if (exists(runDirPath))
180 sessionRunDir = get(runDirPath);
181 else {
182 Content runDir = get(CmsContentRepository.RUN_BASE);
183 // TODO deal with no run dir available?
184 sessionRunDir = runDir.add(uuid.toString(),DName.collection.qName());
185 }
186 }
187 return sessionRunDir;
188 }
189
190 // @Override
191 // public String findNamespace(String prefix) {
192 // return prefixes.get(prefix);
193 // }
194 //
195 // @Override
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());
199 //
200 // return res;
201 // }
202 //
203 // @Override
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);
208 // }
209
210 }