]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/acr/CmsContentSession.java
Prepare next development cycle
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / 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.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;
22
23 /** Implements {@link ProvidedSession}. */
24 class CmsContentSession implements ProvidedSession {
25 final private AbstractContentRepository contentRepository;
26
27 private final UUID uuid;
28 private Subject subject;
29 private Locale locale;
30
31 private UuidFactory uuidFactory;
32
33 private CompletableFuture<ProvidedSession> closed = new CompletableFuture<>();
34
35 private CompletableFuture<ContentSession> edition;
36
37 private Set<ContentProvider> modifiedProviders = new HashSet<>();
38
39 private Content sessionRunDir;
40
41 public CmsContentSession(AbstractContentRepository contentRepository, UUID uuid, Subject subject, Locale locale,
42 UuidFactory uuidFactory) {
43 this.contentRepository = contentRepository;
44 this.subject = subject;
45 this.locale = locale;
46 this.uuid = uuid;
47 this.uuidFactory = uuidFactory;
48 }
49
50 public void close() {
51 closed.complete(this);
52
53 if (sessionRunDir != null)
54 sessionRunDir.remove();
55 }
56
57 @Override
58 public CompletionStage<ProvidedSession> onClose() {
59 return closed.minimalCompletionStage();
60 }
61
62 @Override
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);
70 return content;
71 }
72
73 @Override
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);
81 }
82
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);
87 return relativePath;
88 }
89
90 @Override
91 public Subject getSubject() {
92 return subject;
93 }
94
95 @Override
96 public Locale getLocale() {
97 return locale;
98 }
99
100 @Override
101 public ProvidedRepository getRepository() {
102 return contentRepository;
103 }
104
105 public UuidFactory getUuidFactory() {
106 return uuidFactory;
107 }
108
109 /*
110 * MOUNT MANAGEMENT
111 */
112 @Override
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]);
118 }
119
120 /*
121 * EDITION
122 */
123 @Override
124 public CompletionStage<ContentSession> edit(Consumer<ContentSession> work) {
125 edition = CompletableFuture.supplyAsync(() -> {
126 work.accept(this);
127 return this;
128 }).thenApply((s) -> {
129 synchronized (CmsContentSession.this) {
130 // TODO optimise
131 for (ContentProvider provider : modifiedProviders) {
132 if (provider instanceof DomContentProvider) {
133 ((DomContentProvider) provider).persist(s);
134 }
135 }
136 modifiedProviders.clear();
137 return s;
138 }
139 });
140 return edition.minimalCompletionStage();
141 }
142
143 @Override
144 public boolean isEditing() {
145 return edition != null && !edition.isDone();
146 }
147
148 @Override
149 public synchronized void notifyModification(ProvidedContent content) {
150 ContentProvider contentProvider = content.getProvider();
151 modifiedProviders.add(contentProvider);
152 }
153
154 @Override
155 public UUID getUuid() {
156 return uuid;
157 }
158
159 // @Override
160 public Content getSessionRunDir() {
161 if (sessionRunDir == null) {
162 String runDirPath = CmsContentRepository.RUN_BASE + '/' + uuid.toString();
163 if (exists(runDirPath))
164 sessionRunDir = get(runDirPath);
165 else {
166 Content runDir = get(CmsContentRepository.RUN_BASE);
167 // TODO deal with no run dir available?
168 sessionRunDir = runDir.add(uuid.toString(), DName.collection.qName());
169 }
170 }
171 return sessionRunDir;
172 }
173 }