]> git.argeo.org Git - lgpl/argeo-commons.git/blob - acr/AbstractContentRepository.java
Prepare next development cycle
[lgpl/argeo-commons.git] / acr / 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 MountManager mountManager;
39 private 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 }
60
61 protected abstract CmsContentSession newSystemSession();
62
63 public void start() {
64 systemSession = newSystemSession();
65 // mounts
66 mountManager = new MountManager(systemSession);
67 }
68
69 public void stop() {
70 systemSession.close();
71 systemSession = null;
72 }
73
74 /*
75 * REPOSITORY
76 */
77
78 public void addProvider(ContentProvider provider) {
79 mountManager.addStructuralContentProvider(provider);
80 }
81
82 public void registerTypes(String prefix, String namespaceURI, String schemaSystemId) {
83 typesManager.registerTypes(prefix, namespaceURI, schemaSystemId);
84 }
85
86 /*
87 * FACTORIES
88 */
89 public void initRootContentProvider(Path path) {
90 try {
91 // DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
92 // factory.setNamespaceAware(true);
93 // factory.setXIncludeAware(true);
94 // factory.setSchema(contentTypesManager.getSchema());
95 //
96 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
97
98 Document document;
99 // if (path != null && Files.exists(path)) {
100 // InputSource inputSource = new InputSource(path.toAbsolutePath().toUri().toString());
101 // inputSource.setEncoding(StandardCharsets.UTF_8.name());
102 // // TODO public id as well?
103 // document = dBuilder.parse(inputSource);
104 // } else {
105 document = dBuilder.newDocument();
106 Element root = document.createElementNS(CrName.CR_NAMESPACE_URI, CrName.ROOT.get().toPrefixedString());
107
108 for (String prefix : typesManager.getPrefixes().keySet()) {
109 // root.setAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix,
110 // contentTypesManager.getPrefixes().get(prefix));
111 DomUtils.addNamespace(root, prefix, typesManager.getPrefixes().get(prefix));
112 }
113
114 document.appendChild(root);
115
116 // write it
117 if (path != null) {
118 try (OutputStream out = Files.newOutputStream(path)) {
119 writeDom(document, out);
120 }
121 }
122 // }
123
124 String mountPath = "/";
125 DomContentProvider contentProvider = new DomContentProvider(mountPath, document);
126 addProvider(contentProvider);
127 } catch (DOMException | IOException e) {
128 throw new IllegalStateException("Cannot init ACR root " + path, e);
129 }
130
131 }
132
133 public void writeDom(Document document, OutputStream out) throws IOException {
134 try {
135 Transformer transformer = identityTransformerFactory.newTransformer();
136 transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
137 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
138
139 DOMSource source = new DOMSource(document);
140 typesManager.validate(source);
141 StreamResult result = new StreamResult(out);
142 transformer.transform(source, result);
143 } catch (TransformerException e) {
144 throw new IOException("Cannot write dom", e);
145 }
146 }
147
148 /*
149 * MOUNT MANAGEMENT
150 */
151
152 @Override
153 public ContentProvider getMountContentProvider(Content mountPoint, boolean initialize, QName... types) {
154 String mountPath = mountPoint.getPath();
155 // TODO check consistency with types
156
157 return mountManager.getOrAddMountedProvider(mountPath, (path) -> {
158 DocumentBuilder dBuilder = typesManager.newDocumentBuilder();
159 Document document;
160 if (initialize) {
161 QName firstType = types[0];
162 document = dBuilder.newDocument();
163 String prefix = ((ProvidedContent) mountPoint).getSession().getPrefix(firstType.getNamespaceURI());
164 Element root = document.createElementNS(firstType.getNamespaceURI(),
165 prefix + ":" + firstType.getLocalPart());
166 DomUtils.addNamespace(root, prefix, firstType.getNamespaceURI());
167 document.appendChild(root);
168 } else {
169 try (InputStream in = mountPoint.open(InputStream.class)) {
170 document = dBuilder.parse(in);
171 // TODO check consistency with types
172 } catch (IOException | SAXException e) {
173 throw new IllegalStateException("Cannot load mount from " + mountPoint, e);
174 }
175 }
176 DomContentProvider contentProvider = new DomContentProvider(path, document);
177 return contentProvider;
178 });
179 }
180
181 @Override
182 public boolean shouldMount(QName... types) {
183 if (types.length == 0)
184 return false;
185 QName firstType = types[0];
186 Set<QName> registeredTypes = typesManager.listTypes();
187 if (registeredTypes.contains(firstType))
188 return true;
189 return false;
190 }
191
192 MountManager getMountManager() {
193 return mountManager;
194 }
195
196 TypesManager getTypesManager() {
197 return typesManager;
198 }
199 }