1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.journal.lar;
24  
25  import com.liferay.counter.service.CounterLocalServiceUtil;
26  import com.liferay.portal.kernel.lar.PortletDataContext;
27  import com.liferay.portal.kernel.lar.PortletDataException;
28  import com.liferay.portal.kernel.lar.PortletDataHandler;
29  import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
30  import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.StringMaker;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.util.PortalUtil;
36  import com.liferay.portal.util.PortletKeys;
37  import com.liferay.portlet.journal.NoSuchArticleException;
38  import com.liferay.portlet.journal.model.JournalArticle;
39  import com.liferay.portlet.journal.model.JournalStructure;
40  import com.liferay.portlet.journal.model.JournalTemplate;
41  import com.liferay.portlet.journal.model.impl.JournalArticleImpl;
42  import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
43  import com.liferay.portlet.journal.model.impl.JournalTemplateImpl;
44  import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
45  import com.liferay.portlet.journal.service.JournalStructureLocalServiceUtil;
46  import com.liferay.portlet.journal.service.JournalTemplateLocalServiceUtil;
47  import com.liferay.portlet.journal.service.persistence.JournalArticleUtil;
48  import com.liferay.portlet.journal.service.persistence.JournalStructureUtil;
49  import com.liferay.portlet.journal.service.persistence.JournalTemplateUtil;
50  import com.liferay.util.MapUtil;
51  import com.liferay.util.xml.XMLFormatter;
52  
53  import com.thoughtworks.xstream.XStream;
54  
55  import java.util.List;
56  import java.util.Map;
57  
58  import javax.portlet.PortletPreferences;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  import org.dom4j.Document;
64  import org.dom4j.DocumentHelper;
65  import org.dom4j.Element;
66  
67  /**
68   * <a href="JournalContentPortletDataHandlerImpl.java.html"><b><i>View Source
69   * </i></b></a>
70   *
71   * <p>
72   * Provides the Journal Content portlet export and import functionality, which
73   * is to clone the article, structure, and template referenced in the
74   * Journal Content portlet if the article is associated with the layout's group.
75   * Upon import, new instances of the corresponding articles, structures, and
76   * templates are created or updated. The author of the newly created
77   * objects are determined by the JournalCreationStrategy class defined in
78   * <i>portal.properties</i>.
79   * </p>
80   *
81   * <p>
82   * This <code>PortletDataHandler</code> differs from from
83   * <code>JournalPortletDataHandlerImpl</code> in that it only exports articles
84   * referenced in Journal Content portlets. Articles not displayed in Journal
85   * Content portlets will not be exported unless
86   * <code>JournalPortletDataHandlerImpl</code> is activated.
87   * </p>
88   *
89   * @author Joel Kozikowski
90   * @author Raymond Augé
91   *
92   * @see com.liferay.portlet.journal.lar.JournalCreationStrategy
93   * @see com.liferay.portlet.journal.lar.JournalPortletDataHandlerImpl
94   * @see com.liferay.portal.kernel.lar.PortletDataHandler
95   *
96   */
97  public class JournalContentPortletDataHandlerImpl
98      implements PortletDataHandler {
99  
100     public PortletDataHandlerControl[] getExportControls()
101         throws PortletDataException{
102 
103         return new PortletDataHandlerControl[] {_enableExport};
104     }
105 
106     public PortletDataHandlerControl[] getImportControls()
107         throws PortletDataException{
108 
109         return new PortletDataHandlerControl[] {_enableImport};
110     }
111 
112     public String exportData(
113             PortletDataContext context, String portletId,
114             PortletPreferences prefs)
115         throws PortletDataException {
116 
117         Map parameterMap = context.getParameterMap();
118 
119         boolean exportData = MapUtil.getBoolean(
120             parameterMap, _EXPORT_JOURNAL_CONTENT_DATA,
121             _enableExport.getDefaultState());
122 
123         if (_log.isDebugEnabled()) {
124             if (exportData) {
125                 _log.debug("Exporting data is enabled");
126             }
127             else {
128                 _log.debug("Exporting data is disabled");
129             }
130         }
131 
132         if (!exportData) {
133             return null;
134         }
135 
136         try {
137             String articleId = prefs.getValue("article-id", null);
138 
139             if (articleId == null) {
140                 if (_log.isWarnEnabled()) {
141                     _log.warn(
142                         "No article id found in preferences of portlet " +
143                             portletId);
144                 }
145 
146                 return StringPool.BLANK;
147             }
148 
149             long articleGroupId = GetterUtil.getLong(
150                 prefs.getValue("group-id", StringPool.BLANK));
151 
152             if (articleGroupId <= 0) {
153                 if (_log.isWarnEnabled()) {
154                     _log.warn(
155                         "No group id found in preferences of portlet " +
156                             portletId);
157                 }
158 
159                 return StringPool.BLANK;
160             }
161 
162             JournalArticle article = null;
163 
164             try {
165                 article = JournalArticleLocalServiceUtil.getLatestArticle(
166                     articleGroupId, articleId);
167             }
168             catch (NoSuchArticleException nsae) {
169                 if (_log.isWarnEnabled()) {
170                     _log.warn(
171                         "No article found with company id " +
172                             context.getCompanyId() + ", group id " +
173                                 articleGroupId + " and article id " +
174                                     articleId);
175                 }
176             }
177 
178             if (article == null) {
179                 return StringPool.BLANK;
180             }
181 
182             String articlePrimaryKey = getPrimaryKey(
183                 article.getGroupId(), article.getArticleId());
184 
185             if ((article.getGroupId() == context.getGroupId()) &&
186                 !context.addPrimaryKey(
187                     JournalArticle.class, articlePrimaryKey)) {
188 
189                 XStream xStream = new XStream();
190 
191                 Document doc = DocumentHelper.createDocument();
192 
193                 Element root = doc.addElement("journal-content");
194 
195                 String xml = xStream.toXML(article);
196 
197                 Document tempDoc = PortalUtil.readDocumentFromXML(xml);
198 
199                 List content = root.content();
200 
201                 content.add(tempDoc.getRootElement().createCopy());
202 
203                 String structureId = article.getStructureId();
204 
205                 if (Validator.isNotNull(structureId)) {
206                     String structurePrimaryKey = getPrimaryKey(
207                         article.getGroupId(), structureId);
208 
209                     if (!context.addPrimaryKey(
210                             JournalStructure.class, structurePrimaryKey)) {
211 
212                         JournalStructure structure =
213                             JournalStructureUtil.findByG_S(
214                                 article.getGroupId(), structureId);
215 
216                         xml = xStream.toXML(structure);
217 
218                         tempDoc = PortalUtil.readDocumentFromXML(xml);
219 
220                         content.add(tempDoc.getRootElement().createCopy());
221                     }
222                 }
223 
224                 String templateId = article.getTemplateId();
225 
226                 if (Validator.isNotNull(templateId)) {
227                     String templatePrimaryKey = getPrimaryKey(
228                         article.getGroupId(), templateId);
229 
230                     if (!context.addPrimaryKey(
231                             JournalTemplate.class, templatePrimaryKey)) {
232 
233                         JournalTemplate template =
234                             JournalTemplateUtil.findByG_T(
235                                 article.getGroupId(), templateId);
236 
237                         xml = xStream.toXML(template);
238 
239                         tempDoc = PortalUtil.readDocumentFromXML(xml);
240 
241                         content.add(tempDoc.getRootElement().createCopy());
242                     }
243                 }
244 
245                 return XMLFormatter.toString(doc);
246             }
247             else {
248                 return StringPool.BLANK;
249             }
250         }
251         catch (Exception e) {
252             throw new PortletDataException(e);
253         }
254     }
255 
256     public PortletPreferences importData(
257             PortletDataContext context, String portletId,
258             PortletPreferences prefs, String data)
259         throws PortletDataException {
260 
261         Map parameterMap = context.getParameterMap();
262 
263         boolean importData = MapUtil.getBoolean(
264             parameterMap, _IMPORT_JOURNAL_CONTENT_DATA,
265             _enableImport.getDefaultState());
266 
267         if (_log.isDebugEnabled()) {
268             if (importData) {
269                 _log.debug("Importing data is enabled");
270             }
271             else {
272                 _log.debug("Importing data is disabled");
273             }
274         }
275 
276         if (!importData) {
277             return null;
278         }
279 
280         try {
281             importJournalData(context, portletId, data);
282 
283             // Update the group-id in the display content to reference this
284             // group, since the article is now in this group.
285 
286             prefs.setValue("group-id", String.valueOf(context.getGroupId()));
287 
288             return prefs;
289         }
290         catch (Exception e) {
291             throw new PortletDataException(e);
292         }
293     }
294 
295     protected String getPrimaryKey(long groupId, String key) {
296         StringMaker sm = new StringMaker();
297 
298         sm.append(groupId);
299         sm.append(StringPool.POUND);
300         sm.append(key);
301 
302         return sm.toString();
303     }
304 
305     protected void importJournalData(
306             PortletDataContext context, String portletId, String data)
307         throws Exception {
308 
309         if (Validator.isNull(data)) {
310             return;
311         }
312 
313         JournalCreationStrategy creationStrategy =
314             JournalCreationStrategyFactory.getInstance();
315 
316         XStream xStream = new XStream();
317 
318         Document doc = PortalUtil.readDocumentFromXML(data);
319 
320         Element root = doc.getRootElement();
321 
322         Element el = root.element(JournalArticleImpl.class.getName());
323 
324         Document tempDoc = DocumentHelper.createDocument();
325 
326         tempDoc.content().add(el.createCopy());
327 
328         JournalArticle article =
329             (JournalArticle)xStream.fromXML(XMLFormatter.toString(tempDoc));
330 
331         article.setGroupId(context.getGroupId());
332 
333         JournalArticle oldArticle = null;
334 
335         try {
336             oldArticle =
337                 JournalArticleLocalServiceUtil.getLatestArticle(
338                     context.getGroupId(), article.getArticleId());
339         }
340         catch (NoSuchArticleException nsae) {
341         }
342 
343         if (oldArticle == null) {
344             article.setNew(true);
345             article.setId(CounterLocalServiceUtil.increment());
346 
347             long authorId = creationStrategy.getAuthorUserId(
348                 context.getCompanyId(), context.getGroupId(), article);
349 
350             if (authorId > 0) {
351                 article.setUserId(authorId);
352                 article.setUserName(
353                     creationStrategy.getAuthorUserName(
354                         context.getCompanyId(), context.getGroupId(), article));
355             }
356 
357             long approvedById = creationStrategy.getApprovalUserId(
358                 context.getCompanyId(), context.getGroupId(), article);
359 
360             if (approvedById > 0) {
361                 article.setApprovedByUserId(approvedById);
362                 article.setApprovedByUserName(
363                     creationStrategy.getApprovalUserName(
364                         context.getCompanyId(), context.getGroupId(), article));
365                 article.setApproved(true);
366             }
367             else {
368                 article.setApprovedByUserId(0);
369                 article.setApprovedByUserName(null);
370                 article.setApproved(false);
371             }
372 
373             String newContent = creationStrategy.getTransformedContent(
374                 context.getCompanyId(), context.getGroupId(), article);
375 
376             if (newContent != null) {
377                 article.setContent(newContent);
378             }
379 
380             article = JournalArticleUtil.update(article);
381 
382             boolean addCommunityPermissions =
383                 creationStrategy.addCommunityPermissions(
384                     context.getCompanyId(), context.getGroupId(), article);
385             boolean addGuestPermissions =
386                 creationStrategy.addGuestPermissions(
387                     context.getCompanyId(), context.getGroupId(), article);
388 
389             JournalArticleLocalServiceUtil.addArticleResources(
390                 article, addCommunityPermissions, addGuestPermissions);
391         }
392         else {
393 
394             // TODO If the article already exists, it must either be merged with
395             // the object in the Hibernate session retrieved by fetch above, or
396             // not updated at all.
397 
398             //JournalArticleUtil.update(article, true);
399         }
400 
401         el = root.element(JournalStructureImpl.class.getName());
402 
403         if (el != null) {
404             tempDoc = DocumentHelper.createDocument();
405 
406             tempDoc.content().add(el.createCopy());
407 
408             JournalStructure structure = (JournalStructure)xStream.fromXML(
409                 XMLFormatter.toString(tempDoc));
410 
411             structure.setGroupId(context.getGroupId());
412 
413             if (JournalStructureUtil.fetchByG_S(
414                     context.getGroupId(), structure.getStructureId()) == null) {
415 
416                 structure.setNew(true);
417                 structure.setId(CounterLocalServiceUtil.increment());
418 
419                 long authorId = creationStrategy.getAuthorUserId(
420                     context.getCompanyId(), context.getGroupId(), structure);
421 
422                 if (authorId > 0) {
423                     structure.setUserId(authorId);
424                     structure.setUserName(
425                         creationStrategy.getAuthorUserName(
426                             context.getCompanyId(), context.getGroupId(),
427                             structure));
428                 }
429 
430                 structure = JournalStructureUtil.update(structure);
431 
432                 boolean addCommunityPermissions =
433                     creationStrategy.addCommunityPermissions(
434                         context.getCompanyId(), context.getGroupId(),
435                         structure);
436                 boolean addGuestPermissions =
437                     creationStrategy.addGuestPermissions(
438                         context.getCompanyId(), context.getGroupId(),
439                         structure);
440 
441                 JournalStructureLocalServiceUtil.addStructureResources(
442                     structure, addCommunityPermissions, addGuestPermissions);
443             }
444             else {
445 
446                 // TODO If the structure already exists, it must either be
447                 // merged with the object in the Hibernate session retrieved by
448                 // fetch above, or not updated at all.
449 
450                 //JournalStructureUtil.update(structure, true);
451             }
452         }
453 
454         el = root.element(JournalTemplateImpl.class.getName());
455 
456         if (el != null) {
457             tempDoc = DocumentHelper.createDocument();
458 
459             tempDoc.content().add(el.createCopy());
460 
461             JournalTemplate template = (JournalTemplate)xStream.fromXML(
462                 XMLFormatter.toString(tempDoc));
463 
464             template.setGroupId(context.getGroupId());
465 
466             if (JournalTemplateUtil.fetchByG_T(
467                     context.getGroupId(), template.getTemplateId()) == null) {
468 
469                 template.setNew(true);
470                 template.setId(CounterLocalServiceUtil.increment());
471 
472                 long authorId = creationStrategy.getAuthorUserId(
473                     context.getCompanyId(), context.getGroupId(), template);
474 
475                 if (authorId > 0) {
476                     template.setUserId(authorId);
477                     template.setUserName(
478                         creationStrategy.getAuthorUserName(
479                             context.getCompanyId(), context.getGroupId(),
480                             template));
481                 }
482 
483                 template = JournalTemplateUtil.update(template);
484 
485                 boolean addCommunityPermissions =
486                     creationStrategy.addCommunityPermissions(
487                         context.getCompanyId(), context.getGroupId(), template);
488                 boolean addGuestPermissions =
489                     creationStrategy.addGuestPermissions(
490                         context.getCompanyId(), context.getGroupId(), template);
491 
492                 JournalTemplateLocalServiceUtil.addTemplateResources(
493                     template, addCommunityPermissions, addGuestPermissions);
494             }
495             else {
496 
497                 // TODO If the template already exists, it must either be merged
498                 // with the object in the Hibernate session retrieved by fetch
499                 // above, or not updated at all.
500 
501                 //JournalTemplateUtil.update(template, true);
502             }
503         }
504     }
505 
506     private static final String _EXPORT_JOURNAL_CONTENT_DATA =
507         "export-" + PortletKeys.JOURNAL_CONTENT + "-data";
508 
509     private static final String _IMPORT_JOURNAL_CONTENT_DATA =
510         "import-" + PortletKeys.JOURNAL_CONTENT + "-data";
511 
512     private static final PortletDataHandlerBoolean _enableExport =
513         new PortletDataHandlerBoolean(_EXPORT_JOURNAL_CONTENT_DATA, true, null);
514 
515     private static final PortletDataHandlerBoolean _enableImport =
516         new PortletDataHandlerBoolean(_IMPORT_JOURNAL_CONTENT_DATA, true, null);
517 
518     private static Log _log =
519         LogFactory.getLog(JournalContentPortletDataHandlerImpl.class);
520 
521 }