1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.ecm.webui.component.explorer.versions;
18
19 import java.text.DateFormat;
20 import java.util.Calendar;
21 import java.util.Locale;
22
23 import javax.jcr.Node;
24 import javax.jcr.PathNotFoundException;
25 import javax.jcr.Property;
26 import javax.jcr.RepositoryException;
27 import javax.jcr.version.Version;
28 import javax.jcr.version.VersionHistory;
29
30 import org.apache.commons.lang.StringUtils;
31
32 import org.exoplatform.commons.diff.DiffResult;
33 import org.exoplatform.commons.diff.DiffService;
34 import org.exoplatform.ecm.webui.component.explorer.UIDocumentWorkspace;
35 import org.exoplatform.ecm.webui.utils.Utils;
36 import org.exoplatform.portal.webui.util.Util;
37 import org.exoplatform.services.document.DocumentReader;
38 import org.exoplatform.services.document.DocumentReaderService;
39 import org.exoplatform.services.document.HandlerNotFoundException;
40 import org.exoplatform.services.log.ExoLogger;
41 import org.exoplatform.services.log.Log;
42 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
43 import org.exoplatform.webui.config.annotation.ComponentConfig;
44 import org.exoplatform.webui.config.annotation.EventConfig;
45 import org.exoplatform.webui.core.UIComponent;
46 import org.exoplatform.webui.event.Event;
47 import org.exoplatform.webui.event.EventListener;
48
49
50
51
52
53
54 @ComponentConfig(template = "app:/groovy/webui/component/explorer/versions/UIDiff.gtmpl", events = {
55 @EventConfig(listeners = UIDiff.CompareActionListener.class),
56 @EventConfig(listeners = UIDiff.CloseCompareActionListener.class) })
57 public class UIDiff extends UIComponent {
58 private static final String EXO_LAST_MODIFIED_DATE = "exo:lastModifiedDate";
59
60 private static final Log LOG = ExoLogger.getLogger(UIDiff.class.getName());
61
62 public static final String FROM_PARAM = "from";
63
64 public static final String TO_PARAM = "to";
65
66 private String baseVersionName_;
67
68 private String baseVersionDate_;
69
70 private String baseVersionAuthor_;
71
72 private String baseVersionLabel_;
73
74 private String versionName_;
75
76 private String versionDate_;
77
78 private String versionAuthor_;
79
80 private String versionLabel_;
81
82 private String previousText_ = null;
83
84 private String currentText_ = null;
85
86 private boolean versionCompareable_ = true;
87
88 private String diffResultHTML_ = null;
89
90 private boolean isImage_ = false;
91
92 private String baseImage_ = null;
93
94 private String currentImage_ = null;
95
96 public void setVersions(Node baseVersion, Node version) throws Exception {
97 UIDocumentWorkspace uiDocumentWorkspace = getAncestorOfType(UIDocumentWorkspace.class);
98 UIVersionInfo uiVersionInfo = uiDocumentWorkspace.getChild(UIVersionInfo.class);
99
100 versionCompareable_ = baseVersion != null && version != null && !baseVersion.getUUID().equals(version.getUUID());
101 if (!versionCompareable_) {
102 throw new IllegalStateException("Can't compare both versions");
103 } else {
104 Node versionRootVersion = null;
105 if (version instanceof Version) {
106 versionRootVersion = ((Version) version).getContainingHistory().getRootVersion();
107 } else {
108 versionRootVersion = version.getVersionHistory().getRootVersion();
109 }
110
111 Node baseVersionRootVersion = null;
112 if (baseVersion instanceof Version) {
113 baseVersionRootVersion = ((Version) baseVersion).getContainingHistory().getRootVersion();
114 } else {
115 baseVersionRootVersion = baseVersion.getVersionHistory().getRootVersion();
116 }
117
118 versionCompareable_ = baseVersionRootVersion.getUUID().endsWith(versionRootVersion.getUUID());
119 if (!versionCompareable_) {
120 throw new IllegalStateException("Versions to compare are the same");
121 }
122 }
123
124 Node currentNode = uiVersionInfo.getCurrentNode();
125 VersionHistory versionHistory = currentNode.getVersionHistory();
126 Version rootVersion = versionHistory.getRootVersion();
127
128
129 if (currentNode.getUUID().equals(baseVersion.getUUID())) {
130
131
132 Node tmpNode = baseVersion;
133 baseVersion = version;
134 version = tmpNode;
135 } else if (currentNode.getUUID().equals(version.getUUID())) {
136
137 } else if (baseVersion instanceof Version && version instanceof Version) {
138
139 int baseVersionIndice = Integer.parseInt(baseVersion.getName());
140 int versionNumIndice = Integer.parseInt(version.getName());
141
142 if (baseVersionIndice == versionNumIndice) {
143 throw new IllegalStateException("Can't compare the same version");
144 } else if (baseVersionIndice > versionNumIndice) {
145 Node tmpNode = baseVersion;
146 baseVersion = version;
147 version = tmpNode;
148 }
149 }
150
151
152 baseVersionName_ = ((Version) baseVersion).getName();
153
154 versionName_ = version instanceof Version ? version.getName() : uiVersionInfo.getRootVersionNum();
155
156
157 Calendar modifiedDate = getModifiedDate(baseVersion);
158 baseVersionDate_ = formatDate(modifiedDate);
159
160
161 modifiedDate = getModifiedDate(version);
162 versionDate_ = formatDate(modifiedDate);
163
164 baseVersionAuthor_ = getLastModifier(baseVersion);
165 versionAuthor_ = getLastModifier(version);
166
167
168 String[] baseVersionLabels = versionHistory.getVersionLabels((Version) baseVersion);
169 baseVersionLabel_ = baseVersionLabels == null || baseVersionLabels.length == 0 ? null : baseVersionLabels[0];
170
171 if (version instanceof Version) {
172 String[] versionLabels = versionHistory.getVersionLabels((Version) version);
173 versionLabel_ = versionLabels == null || versionLabels.length == 0 ? null : versionLabels[0];
174 } else {
175 String[] versionLabels = versionHistory.getVersionLabels(rootVersion);
176 versionLabel_ = versionLabels == null || versionLabels.length == 0 ? null : versionLabels[0];
177 }
178
179 isImage_ = isOriginalNodeImage(version) && isOriginalNodeImage(baseVersion);
180
181 previousText_ = null;
182 currentText_ = null;
183 diffResultHTML_ = null;
184 currentImage_ = null;
185 baseImage_ = null;
186 isImage_ = isOriginalNodeImage(version) && isOriginalNodeImage(baseVersion);
187
188 if (isImage_) {
189 String wsName = currentNode.getSession().getWorkspace().getName();
190 String originalNodePath = currentNode.getPath();
191 String basePath = "/" + WCMCoreUtils.getPortalName() + "/" + WCMCoreUtils.getRestContextName() + "/jcr/"
192 + WCMCoreUtils.getRepository().getConfiguration().getName() + "/" + wsName + originalNodePath;
193
194 long timeInMS = Calendar.getInstance().getTimeInMillis();
195
196 currentImage_ = basePath + (currentNode.getUUID().equals(version.getUUID()) ? "?" + timeInMS : ("?version=" + version.getName() + "&" + timeInMS));
197 baseImage_ = basePath + (currentNode.getUUID().equals(baseVersion.getUUID()) ? "?" + timeInMS : "?version=" + baseVersion.getName() + "&" + timeInMS);
198 } else {
199 try {
200 previousText_ = getText(baseVersion);
201 currentText_ = getText(version);
202 } catch (HandlerNotFoundException e) {
203 versionCompareable_ = false;
204 }
205
206 if (versionCompareable_) {
207 if (StringUtils.isBlank(previousText_) && StringUtils.isBlank(currentText_)) {
208 versionCompareable_ = false;
209 } else if ((previousText_ != null) && (currentText_ != null)) {
210 DiffService diffService = WCMCoreUtils.getService(DiffService.class);
211 DiffResult diffResult = diffService.getDifferencesAsHTML(previousText_, currentText_, true);
212 diffResultHTML_ = diffResult.getDiffHTML();
213 }
214 }
215 }
216 }
217
218 public String getBaseVersionNum() throws Exception {
219 return baseVersionName_;
220 }
221
222 public String getCurrentVersionNum() throws Exception {
223 return versionName_;
224 }
225
226 public String getBaseVersionDate() throws Exception {
227 return baseVersionDate_;
228 }
229
230 public String getCurrentVersionDate() throws Exception {
231 return versionDate_;
232 }
233
234 public String getBaseVersionAuthor() {
235 return baseVersionAuthor_;
236 }
237
238 public String getCurrentVersionAuthor() {
239 return versionAuthor_;
240 }
241
242 public String getBaseVersionLabel() {
243 return baseVersionLabel_;
244 }
245
246 public String getCurrentVersionLabel() {
247 return versionLabel_;
248 }
249
250 public String getBaseImage() throws Exception {
251 return baseImage_;
252 }
253
254 public String getCurrentImage() throws Exception {
255 return currentImage_;
256 }
257
258 public boolean isCompareable() {
259 return versionCompareable_;
260 }
261
262 public String getDifferences() throws Exception {
263 return diffResultHTML_;
264 }
265
266 public boolean isImage() {
267 return isImage_;
268 }
269
270 private Calendar getModifiedDate(Node node) throws RepositoryException {
271 Property property = getProperty(node, EXO_LAST_MODIFIED_DATE);
272 return property == null ? null : property.getDate();
273 }
274
275 private String getLastModifier(Node node) throws RepositoryException {
276 Property property = getProperty(node, Utils.EXO_LASTMODIFIER);
277 return property == null ? null : property.getString();
278 }
279
280 private boolean isOriginalNodeImage(Node node) throws Exception {
281 Property mimeProperty = getProperty(node, Utils.JCR_MIMETYPE);
282 String mimeType = mimeProperty == null ? null : mimeProperty.getString();
283 return StringUtils.isNotBlank(mimeType) && mimeType.startsWith("image");
284 }
285
286 private String getText(Node node) throws Exception {
287 Property mimeProperty = getProperty(node, Utils.JCR_MIMETYPE);
288 Property dataProperty = getProperty(node, Utils.JCR_DATA);
289 if (mimeProperty != null && dataProperty != null) {
290 String mimeType = mimeProperty.getString();
291 if (mimeType.startsWith("text")) {
292 return dataProperty.getString();
293 }
294 DocumentReaderService readerService = getApplicationComponent(DocumentReaderService.class);
295 DocumentReader documentReader = readerService.getDocumentReader(mimeType);
296 if (documentReader != null) {
297 try {
298 return documentReader.getContentAsText(dataProperty.getStream());
299 } catch (Exception e) {
300 LOG.warn("An error occured while getting text from file " + node.getPath() + " with mimeType " + mimeType
301 + " with document reader = " + documentReader + ". File comparaison will be disabled", e);
302 }
303 }
304 }
305 throw new HandlerNotFoundException();
306 }
307
308 private Property getProperty(Node node, String propertyName) throws RepositoryException, PathNotFoundException {
309 Property property = null;
310 if (node instanceof Version) {
311 if (node.hasNode(Utils.JCR_FROZEN)) {
312 node = node.getNode(Utils.JCR_FROZEN);
313 } else {
314 return null;
315 }
316 }
317 if (node.hasProperty(propertyName)) {
318 property = node.getProperty(propertyName);
319 } else if (node.hasNode(Utils.JCR_CONTENT)) {
320 Node content = node.getNode(Utils.JCR_CONTENT);
321 if (content.hasProperty(propertyName)) {
322 property = content.getProperty(propertyName);
323 }
324 }
325 return property;
326 }
327
328 private String formatDate(Calendar calendar) {
329 Locale currentLocale = Util.getPortalRequestContext().getLocale();
330 DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT, currentLocale);
331 return dateFormat.format(calendar.getTime());
332 }
333
334 static public class CloseCompareActionListener extends EventListener<UIDiff> {
335 public void execute(Event<UIDiff> event) throws Exception {
336 UIDiff uiDiff = event.getSource();
337 if (uiDiff.isRendered()) {
338 uiDiff.setRendered(false);
339 }
340 UIDocumentWorkspace uiDocumentWorkspace = uiDiff.getAncestorOfType(UIDocumentWorkspace.class);
341 UIVersionInfo uiVersionInfo = uiDocumentWorkspace.getChild(UIVersionInfo.class);
342 uiVersionInfo.setRendered(true);
343 event.getRequestContext().addUIComponentToUpdateByAjax(uiDocumentWorkspace);
344 }
345 }
346
347 static public class CompareActionListener extends EventListener<UIDiff> {
348 public void execute(Event<UIDiff> event) throws Exception {
349 UIDiff uiDiff = (UIDiff) event.getSource();
350 String fromVersionName = event.getRequestContext().getRequestParameter(FROM_PARAM);
351 String toVersionName = event.getRequestContext().getRequestParameter(TO_PARAM);
352 UIDocumentWorkspace uiDocumentWorkspace = uiDiff.getAncestorOfType(UIDocumentWorkspace.class);
353 UIVersionInfo uiVersionInfo = uiDocumentWorkspace.getChild(UIVersionInfo.class);
354 uiDiff.setVersions(uiVersionInfo.getVersion(fromVersionName), uiVersionInfo.getVersion(toVersionName));
355 }
356 }
357 }