1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.frontend.xeditor;
20
21 import java.io.IOException;
22 import java.util.Collections;
23 import java.util.HashMap;
24 import java.util.Iterator;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import java.util.regex.Matcher;
28 import java.util.regex.Pattern;
29
30 import javax.xml.transform.TransformerException;
31
32 import org.apache.logging.log4j.LogManager;
33 import org.apache.logging.log4j.Logger;
34 import org.jdom2.Document;
35 import org.jdom2.Element;
36 import org.jdom2.JDOMException;
37 import org.jdom2.Namespace;
38 import org.jdom2.Verifier;
39 import org.mycore.common.MCRConstants;
40 import org.mycore.common.config.MCRConfiguration2;
41 import org.mycore.common.content.MCRSourceContent;
42 import org.mycore.common.xsl.MCRParameterCollector;
43 import org.mycore.frontend.xeditor.tracker.MCRBreakpoint;
44 import org.mycore.frontend.xeditor.tracker.MCRChangeTracker;
45 import org.mycore.frontend.xeditor.validation.MCRXEditorValidator;
46 import org.xml.sax.SAXException;
47
48
49
50
51 public class MCREditorSession {
52
53 private static final Logger LOGGER = LogManager.getLogger(MCREditorSession.class);
54
55 private static final Pattern PATTERN_URI = Pattern.compile("\\{\\$([^\\}]+)\\}");
56
57 private String id;
58
59 private String url;
60
61 private Map<String, String[]> requestParameters = new HashMap<>();
62
63 private Map<String, Object> variables;
64
65 private String cancelURL;
66
67 private Document editedXML;
68
69 private MCRChangeTracker tracker = new MCRChangeTracker();
70
71 private MCREditorSubmission submission = new MCREditorSubmission(this);
72
73 private MCRXEditorValidator validator = new MCRXEditorValidator(this);
74
75 private MCRXMLCleaner cleaner = new MCRXMLCleaner();
76
77 private MCRXEditorPostProcessor postProcessor = getDefaultPostProcessorImplementation();
78
79 private static MCRPostProcessorXSL getDefaultPostProcessorImplementation() {
80 return MCRConfiguration2.getOrThrow("MCR.XEditor.PostProcessor.Default", MCRConfiguration2::instantiateClass);
81 }
82
83 public MCREditorSession(Map<String, String[]> requestParameters, MCRParameterCollector collector) {
84
85 this.requestParameters.putAll(requestParameters);
86 this.variables = new HashMap<>(collector.getParameterMap());
87 removeIllegalVariables();
88 }
89
90 public MCREditorSession() {
91 this(Collections.emptyMap(), new MCRParameterCollector());
92 }
93
94 public Map<String, Object> getVariables() {
95 return variables;
96 }
97
98 public void update(MCRParameterCollector collector) {
99 String currentLang = collector.getParameter("CurrentLang", null);
100 if (currentLang != null) {
101 variables.put("CurrentLang", currentLang);
102 }
103 }
104
105 private void removeIllegalVariables() {
106 for (Iterator<Entry<String, Object>> entries = variables.entrySet().iterator(); entries.hasNext();) {
107 String name = entries.next().getKey();
108 String result = Verifier.checkXMLName(name);
109 if (result != null) {
110 LOGGER.warn("Illegally named transformation parameter, removing {}", name);
111 entries.remove();
112 }
113 }
114 }
115
116 public void setID(String id) {
117 this.id = id;
118 }
119
120 public String getID() {
121 return id;
122 }
123
124 public String getCombinedSessionStepID() {
125 return id + "-" + tracker.getChangeCounter();
126 }
127
128 public void setPageURL(String pageURL) {
129 if (url == null) {
130 this.url = pageURL.contains("?") ? pageURL.substring(0, pageURL.indexOf("?")) : pageURL;
131 LOGGER.debug("Editor page URL set to {}", this.url);
132 }
133 }
134
135 public String getPageURL() {
136 return this.url;
137 }
138
139 public String getRedirectURL(String anchor) {
140 return url + "?" + MCREditorSessionStore.XEDITOR_SESSION_PARAM + "=" + id
141 + (anchor != null ? "#" + anchor : "");
142 }
143
144 public Map<String, String[]> getRequestParameters() {
145 return requestParameters;
146 }
147
148 public String getCancelURL() {
149 return cancelURL;
150 }
151
152 public void setCancelURL(String cancelURL) {
153 if (this.cancelURL != null) {
154 return;
155 }
156
157 String cURL = replaceParameters(cancelURL);
158 if (!cURL.contains("{")) {
159 LOGGER.debug("{} set cancel URL to {}", id, cURL);
160 this.cancelURL = cURL;
161 }
162 }
163
164 public String replaceParameters(String uri) {
165 Matcher m = PATTERN_URI.matcher(uri);
166 StringBuffer sb = new StringBuffer();
167 while (m.find()) {
168 String token = m.group(1);
169 Object value = variables.get(token);
170 m.appendReplacement(sb, value == null ? m.group().replace("$", "\\$") : value.toString());
171 }
172 m.appendTail(sb);
173 return sb.toString();
174 }
175
176 public Document getEditedXML() {
177 return editedXML;
178 }
179
180 public void setEditedXML(Document editedXML) throws JDOMException {
181 this.editedXML = editedXML;
182 addNamespacesFrom(editedXML.getRootElement());
183 }
184
185 private void addNamespacesFrom(Element element) {
186 MCRConstants.registerNamespace(element.getNamespace());
187 for (Namespace ns : element.getAdditionalNamespaces()) {
188 MCRConstants.registerNamespace(ns);
189 }
190 for (Element child : element.getChildren()) {
191 addNamespacesFrom(child);
192 }
193 }
194
195 public void setEditedXML(String uri) throws JDOMException, IOException, SAXException, TransformerException {
196 String uriRe = replaceParameters(uri);
197 if ((editedXML != null) || uriRe.contains("{")) {
198 return;
199 }
200
201 LOGGER.info("Reading edited XML from {}", uriRe);
202 Document xml = MCRSourceContent.getInstance(uriRe).asXML();
203 setEditedXML(xml);
204 setBreakpoint("Reading XML from " + uriRe);
205 }
206
207 public MCRBinding getRootBinding() throws JDOMException {
208 MCRBinding binding = new MCRBinding(editedXML, tracker);
209 binding.setVariables(variables);
210 return binding;
211 }
212
213 public void setBreakpoint(String msg) {
214 if (editedXML != null) {
215 tracker.track(MCRBreakpoint.setBreakpoint(editedXML.getRootElement(), msg));
216 }
217 }
218
219 public MCRChangeTracker getChangeTracker() {
220 return tracker;
221 }
222
223 public MCREditorSubmission getSubmission() {
224 return submission;
225 }
226
227 public MCRXEditorValidator getValidator() {
228 return validator;
229 }
230
231 public MCRXMLCleaner getXMLCleaner() {
232 return cleaner;
233 }
234
235 public MCRXEditorPostProcessor getPostProcessor() {
236 return postProcessor;
237 }
238
239 protected void setPostProcessor(MCRXEditorPostProcessor postProcessor) {
240 this.postProcessor = postProcessor;
241 }
242
243 }