]> git.argeo.org Git - lgpl/argeo-commons.git/blob - AbstractContentRepository.java
382c432b564f4fe1c46bd17fa49ed3166c756f31
[lgpl/argeo-commons.git] / AbstractContentRepository.java
1 package org.argeo.cms.acr;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.OutputStream;
6 import java.nio.file.Files;
7 import java.nio.file.Path;
8 import java.util.Set;
9
10 import javax.xml.namespace.QName;
11 import javax.xml.parsers.DocumentBuilder;
12 import javax.xml.transform.OutputKeys;
13 import javax.xml.transform.Transformer;
14 import javax.xml.transform.TransformerException;
15 import javax.xml.transform.TransformerFactory;
16 import javax.xml.transform.dom.DOMSource;
17 import javax.xml.transform.stream.StreamResult;
18
19 import org.argeo.api.acr.Content;
20 import org.argeo.api.acr.CrName;
21 import org.argeo.api.acr.spi.ContentProvider;
22 import org.argeo.api.acr.spi.ProvidedContent;
23 import org.argeo.api.acr.spi.ProvidedRepository;
24 import org.argeo.api.cms.CmsLog;
25 import org.argeo.cms.acr.xml.DomContentProvider;
26 import org.argeo.cms.acr.xml.DomUtils;
27 import org.w3c.dom.DOMException;
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.xml.sax.SAXException;
31
32 /**
33 * Base implementation of a {@link ProvidedRepository}.
34 */
35 public abstract class AbstractContentRepository implements ProvidedRepository {
36 private final static CmsLog log = CmsLog.getLog(AbstractContentRepository.class);
37
38 private final MountManager mountManager;
39 private final TypesManager typesManager;
40
41 private CmsContentSession systemSession;
42
43 // utilities
44 /** Should be used only to copy source and results. */
45 private TransformerFactory identityTransformerFactory = TransformerFactory.newInstance();
46
47 public final static String ACR_MOUNT_PATH_PROPERTY = "acr.mount.path";
48
49 public AbstractContentRepository() {
50 // types
51 typesManager = new TypesManager();
52 typesManager.init();
53 Set<QName> types = typesManager.listTypes();
54 if (log.isTraceEnabled())
55 for (QName type : types) {
56 log.trace(type + " - " + typesManager.getAttributeTypes(type));
57 }
58
59 systemSession = newSystemSession();
60
61 // mounts
62 mountManager = new MountManager(systemSession);
63
64 }
65
66 protected abstract CmsContentSession newSystemSession();
67
68 public void start() {
69 }
70
71 public void stop() {
72
73 }
74
75 /*
76 * REPOSITORY
77 */
78
79 public void addProvider(ContentProvider provider) {
80 mountManager.addStructuralContentProvider(provider);
81 }
82
83 public void registerTypes(String prefix, String namespaceURI, String schemaSystemId) {
84 typesManager.registerTypes(prefix, namespaceURI, schemaSystemId);
85 }
86
87 /*
88 * FACTORIES
89 */
90 public void initRootContentProvider(Path path) {
91 try {
92 // DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
93 // factory.setNamespaceAware(true);
94 // factory.setXIncludeAware(true);
95 // factory.setSchema(contentTypesManager.getSchema());
96 //
97 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
98
99 Document document;
100 // if (path != null && Files.exists(path)) {
101 // InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString());
102 // inputSource.setEncoding(StandardCharsets.UTF_8.name());
103 // // TODO public id as well?
104 // document = dBuilder.parse(inputSource);
105 // } else {
106 document = dBuilder.newDocument();
107 Element root = document.createElementNS(CrName.CR_NAMESPACE_URI, CrName.ROOT.get().toPrefixedString());
108
109 for (String prefix : typesManager.getPrefixes().keySet()) {
110 // root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
111 // contentTypesManager.getPrefixes().get(prefix));
112 DomUtils.addNamespace(root, prefix, typesManager.getPrefixes().get(prefix));
113 }
114
115 document.appendChild(root);
116
117 // write it
118 if (path != null) {
119 try (OutputStream out = Files.newOutputStream(path)) {
120 writeDom(document, out);
121 }
122 }
123 // }
124
125 String mountPath = "/";
126 DomContentProvider contentProvider = new DomContentProvider(mountPath, document);
127 addProvider(contentProvider);
128 } catch (DOMException | IOException e) {
129 throw new IllegalStateException("Cannot init ACR root " + path, e);
130 }
131
132 }
133
134 public void writeDom(Document document, OutputStream out) throws IOException {
135 try {
136 Transformer transformer = identityTransformerFactory.newTransformer();
137 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
138 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
139
140 DOMSource source = new DOMSource(document);
141 typesManager.validate(source);
142 StreamResult result = new StreamResult(out);
143 transformer.transform(source, result);
144 } catch (TransformerException e) {
145 throw new IOException("Cannot write dom", e);
146 }
147 }
148
149 /*
150 * MOUNT MANAGEMENT
151 */
152
153 @Override
154 public ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types) {
155 String mountPath = mountPoint.getPath();
156 // TODO check consistency with types
157
158 return mountManager.getOrAddMountedProvider(mountPath, (path) -> {
159 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
160 Document document;
161 if (initialize) {
162 QName firstType = types[0];
163 document = dBuilder.newDocument();
164 String prefix = ((ProvidedContent) mountPoint).getSession().getPrefix(firstType.getNamespaceURI());
165 Element root = document.createElementNS(firstType.getNamespaceURI(),
166 prefix + ":" + firstType.getLocalPart());
167 DomUtils.addNamespace(root, prefix, firstType.getNamespaceURI());
168 document.appendChild(root);
169 } else {
170 try (InputStream in = mountPoint.open(InputStream.class)) {
171 document = dBuilder.parse(in);
172 // TODO check consistency with types
173 } catch (IOException | SAXException e) {
174 throw new IllegalStateException("Cannot load mount from " + mountPoint, e);
175 }
176 }
177 DomContentProvider contentProvider = new DomContentProvider(path, document);
178 return contentProvider;
179 });
180 }
181
182 @Override
183 public boolean shouldMount(QName... types) {
184 if (types.length == 0)
185 return false;
186 QName firstType = types[0];
187 Set<QName> registeredTypes = typesManager.listTypes();
188 if (registeredTypes.contains(firstType))
189 return true;
190 return false;
191 }
192
193 MountManager getMountManager() {
194 return mountManager;
195 }
196
197 TypesManager getTypesManager() {
198 return typesManager;
199 }
200
201 }