1 package org
.argeo
.cms
.acr
;
4 import java
.util
.NavigableMap
;
5 import java
.util
.Objects
;
6 import java
.util
.TreeMap
;
7 import java
.util
.function
.Function
;
9 import org
.argeo
.api
.acr
.Content
;
10 import org
.argeo
.api
.acr
.CrName
;
11 import org
.argeo
.api
.acr
.spi
.ContentProvider
;
13 /** Manages the structural and dynamic mounts within the content repository. */
15 private final NavigableMap
<String
, ContentProvider
> partitions
= new TreeMap
<>();
17 private final CmsContentSession systemSession
;
19 public MountManager(CmsContentSession systemSession
) {
20 this.systemSession
= systemSession
;
23 synchronized void addStructuralContentProvider(ContentProvider contentProvider
) {
24 String mountPath
= contentProvider
.getMountPath();
25 Objects
.requireNonNull(mountPath
);
26 if (partitions
.containsKey(mountPath
))
27 throw new IllegalStateException("A provider is already registered for " + mountPath
);
28 partitions
.put(mountPath
, contentProvider
);
29 if ("/".equals(mountPath
))// root
31 String
[] parentPath
= CmsContent
.getParentPath(mountPath
);
32 Content parent
= systemSession
.get(parentPath
[0]);
33 Content mount
= parent
.add(parentPath
[1]);
34 mount
.put(CrName
.mount
.qName(), "true");
38 synchronized ContentProvider
getOrAddMountedProvider(String mountPath
, Function
<String
, ContentProvider
> factory
) {
39 Objects
.requireNonNull(factory
);
40 if (!partitions
.containsKey(mountPath
)) {
41 ContentProvider contentProvider
= factory
.apply(mountPath
);
42 if (!mountPath
.equals(contentProvider
.getMountPath()))
43 throw new IllegalArgumentException("Mount path " + mountPath
+ " is inconsistent with content provider "
44 + contentProvider
.getMountPath());
45 partitions
.put(mountPath
, contentProvider
);
47 return partitions
.get(mountPath
);
50 /** The content provider for this path. */
51 synchronized ContentProvider
findContentProvider(String path
) {
52 // if (ContentUtils.EMPTY.equals(path))
53 // return partitions.firstEntry().getValue();
54 Map
.Entry
<String
, ContentProvider
> floorEntry
= partitions
.floorEntry(path
);
55 if (floorEntry
== null)
56 throw new IllegalArgumentException("No floor entry provider found for path '" + path
+ "'");
57 String mountPath
= floorEntry
.getKey();
58 if (!path
.startsWith(mountPath
)) {
59 // FIXME make it more robust and find when there is no content provider
60 String
[] parent
= CmsContent
.getParentPath(path
);
61 return findContentProvider(parent
[0]);
62 // throw new IllegalArgumentException("Path " + path + " doesn't have a content
65 ContentProvider contentProvider
= floorEntry
.getValue();
66 assert mountPath
.equals(contentProvider
.getMountPath());
67 return contentProvider
;
70 /** All content providers under this path. */
71 synchronized NavigableMap
<String
, ContentProvider
> findContentProviders(String path
) {
72 Map
.Entry
<String
, ContentProvider
> floorEntry
= partitions
.floorEntry(path
);
73 if (floorEntry
== null)
74 throw new IllegalArgumentException("No floor entry provider found for path '" + path
+ "'");
75 // we first find the parent provider
76 String parentProviderPath
= floorEntry
.getKey();
77 // then gather all sub-providers
78 NavigableMap
<String
, ContentProvider
> res
= new TreeMap
<>();
79 res
.put(floorEntry
.getKey(), floorEntry
.getValue());
80 tail
: for (Map
.Entry
<String
, ContentProvider
> provider
: partitions
.tailMap(parentProviderPath
).entrySet()) {
81 if (!provider
.getKey().startsWith(path
))
83 res
.put(provider
.getKey(), provider
.getValue());