001
014
015 package com.liferay.portal.kernel.lar;
016
017 import com.liferay.portal.NoSuchModelException;
018 import com.liferay.portal.kernel.exception.PortalException;
019 import com.liferay.portal.kernel.lar.lifecycle.ExportImportLifecycleConstants;
020 import com.liferay.portal.kernel.lar.lifecycle.ExportImportLifecycleManager;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.util.ArrayUtil;
024 import com.liferay.portal.kernel.util.GetterUtil;
025 import com.liferay.portal.kernel.util.MapUtil;
026 import com.liferay.portal.kernel.util.TransientValue;
027 import com.liferay.portal.kernel.workflow.WorkflowConstants;
028 import com.liferay.portal.kernel.xml.Element;
029 import com.liferay.portal.model.Group;
030 import com.liferay.portal.model.LocalizedModel;
031 import com.liferay.portal.model.StagedModel;
032 import com.liferay.portal.model.TrashedModel;
033 import com.liferay.portal.model.WorkflowedModel;
034 import com.liferay.portal.service.GroupLocalServiceUtil;
035 import com.liferay.portlet.asset.model.AssetCategory;
036 import com.liferay.portlet.asset.service.AssetCategoryLocalServiceUtil;
037 import com.liferay.portlet.messageboards.model.MBDiscussion;
038 import com.liferay.portlet.messageboards.model.MBMessage;
039 import com.liferay.portlet.messageboards.service.MBDiscussionLocalServiceUtil;
040 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
041 import com.liferay.portlet.ratings.model.RatingsEntry;
042 import com.liferay.portlet.ratings.service.RatingsEntryLocalServiceUtil;
043 import com.liferay.portlet.sitesadmin.lar.StagedGroup;
044
045 import java.util.ArrayList;
046 import java.util.HashMap;
047 import java.util.List;
048 import java.util.Map;
049
050
055 public abstract class BaseStagedModelDataHandler<T extends StagedModel>
056 implements StagedModelDataHandler<T> {
057
058 @Override
059 public abstract void deleteStagedModel(
060 String uuid, long groupId, String className, String extraData)
061 throws PortalException;
062
063 @Override
064 public void exportStagedModel(
065 PortletDataContext portletDataContext, T stagedModel)
066 throws PortletDataException {
067
068 validateExport(portletDataContext, stagedModel);
069
070 String path = ExportImportPathUtil.getModelPath(stagedModel);
071
072 if (portletDataContext.isPathExportedInScope(path)) {
073 return;
074 }
075
076 try {
077 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
078 ExportImportLifecycleConstants.
079 EVENT_STAGED_MODEL_EXPORT_STARTED,
080 PortletDataContextFactoryUtil.clonePortletDataContext(
081 portletDataContext),
082 new TransientValue<T>(stagedModel));
083
084 ManifestSummary manifestSummary =
085 portletDataContext.getManifestSummary();
086
087 PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
088 "stagedModel", stagedModel, manifestSummary);
089
090 doExportStagedModel(portletDataContext, (T)stagedModel.clone());
091
092 exportAssetCategories(portletDataContext, stagedModel);
093 exportComments(portletDataContext, stagedModel);
094 exportRatings(portletDataContext, stagedModel);
095
096 if (countStagedModel(portletDataContext, stagedModel)) {
097 manifestSummary.incrementModelAdditionCount(
098 stagedModel.getStagedModelType());
099 }
100
101 portletDataContext.cleanUpMissingReferences(stagedModel);
102
103 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
104 ExportImportLifecycleConstants.
105 EVENT_STAGED_MODEL_EXPORT_SUCCEEDED,
106 PortletDataContextFactoryUtil.clonePortletDataContext(
107 portletDataContext),
108 new TransientValue<T>(stagedModel));
109 }
110 catch (PortletDataException pde) {
111 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
112 ExportImportLifecycleConstants.EVENT_STAGED_MODEL_EXPORT_FAILED,
113 PortletDataContextFactoryUtil.clonePortletDataContext(
114 portletDataContext),
115 new TransientValue<T>(stagedModel), pde);
116
117 throw pde;
118 }
119 catch (Throwable t) {
120 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
121 ExportImportLifecycleConstants.EVENT_STAGED_MODEL_EXPORT_FAILED,
122 PortletDataContextFactoryUtil.clonePortletDataContext(
123 portletDataContext),
124 new TransientValue<T>(stagedModel), t);
125
126 PortletDataException pde = new PortletDataException(t);
127
128 if (t instanceof NoSuchModelException) {
129 pde.setStagedModel(stagedModel);
130 pde.setType(PortletDataException.MISSING_DEPENDENCY);
131 }
132
133 throw pde;
134 }
135 }
136
137 @Override
138 public T fetchMissingReference(String uuid, long groupId) {
139
140
141
142 T existingStagedModel = fetchStagedModelByUuidAndGroupId(uuid, groupId);
143
144 if (existingStagedModel != null) {
145 return existingStagedModel;
146 }
147
148 try {
149
150
151
152 Group originalGroup = GroupLocalServiceUtil.getGroup(groupId);
153
154 Group group = originalGroup.getParentGroup();
155
156 while (group != null) {
157 existingStagedModel = fetchStagedModelByUuidAndGroupId(
158 uuid, group.getGroupId());
159
160 if (existingStagedModel != null) {
161 break;
162 }
163
164 group = group.getParentGroup();
165 }
166
167 if (existingStagedModel == null) {
168 existingStagedModel = fetchStagedModelByUuidAndCompanyId(
169 uuid, originalGroup.getCompanyId());
170 }
171
172 return existingStagedModel;
173 }
174 catch (Exception e) {
175 if (_log.isDebugEnabled()) {
176 _log.debug(e, e);
177 }
178 else if (_log.isWarnEnabled()) {
179 _log.warn(
180 "Unable to fetch missing reference staged model from " +
181 "group " + groupId);
182 }
183
184 return null;
185 }
186 }
187
188 @Override
189 public abstract T fetchStagedModelByUuidAndCompanyId(
190 String uuid, long companyId);
191
192 @Override
193 public T fetchStagedModelByUuidAndGroupId(String uuid, long groupId) {
194 return null;
195 }
196
197 @Override
198 public abstract String[] getClassNames();
199
200 @Override
201 public String getDisplayName(T stagedModel) {
202 return stagedModel.getUuid();
203 }
204
205 @Override
206 public int[] getExportableStatuses() {
207 return new int[] {WorkflowConstants.STATUS_APPROVED};
208 }
209
210 @Override
211 public Map<String, String> getReferenceAttributes(
212 PortletDataContext portletDataContext, T stagedModel) {
213
214 return new HashMap<String, String>();
215 }
216
217
221 @Deprecated
222 @Override
223 public void importCompanyStagedModel(
224 PortletDataContext portletDataContext, Element referenceElement)
225 throws PortletDataException {
226
227 importMissingReference(portletDataContext, referenceElement);
228 }
229
230
235 @Deprecated
236 @Override
237 public void importCompanyStagedModel(
238 PortletDataContext portletDataContext, String uuid, long classPK)
239 throws PortletDataException {
240
241 importMissingReference(
242 portletDataContext, uuid, portletDataContext.getCompanyGroupId(),
243 classPK);
244 }
245
246 @Override
247 public void importMissingReference(
248 PortletDataContext portletDataContext, Element referenceElement)
249 throws PortletDataException {
250
251 importMissingGroupReference(portletDataContext, referenceElement);
252
253 String uuid = referenceElement.attributeValue("uuid");
254
255 Map<Long, Long> groupIds =
256 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
257 Group.class);
258
259 long liveGroupId = GetterUtil.getLong(
260 referenceElement.attributeValue("live-group-id"));
261
262 liveGroupId = MapUtil.getLong(groupIds, liveGroupId);
263
264 long classPK = GetterUtil.getLong(
265 referenceElement.attributeValue("class-pk"));
266
267 importMissingReference(portletDataContext, uuid, liveGroupId, classPK);
268 }
269
270 @Override
271 public void importMissingReference(
272 PortletDataContext portletDataContext, String uuid, long groupId,
273 long classPK)
274 throws PortletDataException {
275
276 try {
277 doImportMissingReference(
278 portletDataContext, uuid, groupId, classPK);
279 }
280 catch (PortletDataException pde) {
281 throw pde;
282 }
283 catch (Exception e) {
284 throw new PortletDataException(e);
285 }
286 }
287
288 @Override
289 public void importStagedModel(
290 PortletDataContext portletDataContext, T stagedModel)
291 throws PortletDataException {
292
293 String path = ExportImportPathUtil.getModelPath(stagedModel);
294
295 if (portletDataContext.isPathProcessed(path)) {
296 return;
297 }
298
299 try {
300 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
301 ExportImportLifecycleConstants.
302 EVENT_STAGED_MODEL_IMPORT_STARTED,
303 PortletDataContextFactoryUtil.clonePortletDataContext(
304 portletDataContext),
305 new TransientValue<T>(stagedModel));
306
307 ManifestSummary manifestSummary =
308 portletDataContext.getManifestSummary();
309
310 PortletDataHandlerStatusMessageSenderUtil.sendStatusMessage(
311 "stagedModel", stagedModel, manifestSummary);
312
313 if (stagedModel instanceof LocalizedModel) {
314 LocalizedModel localizedModel = (LocalizedModel)stagedModel;
315
316 localizedModel.prepareLocalizedFieldsForImport();
317 }
318
319 if (stagedModel instanceof TrashedModel) {
320 restoreStagedModel(portletDataContext, stagedModel);
321 }
322
323 importAssetCategories(portletDataContext, stagedModel);
324
325 importReferenceStagedModels(portletDataContext, stagedModel);
326
327 doImportStagedModel(portletDataContext, stagedModel);
328
329 importComments(portletDataContext, stagedModel);
330 importRatings(portletDataContext, stagedModel);
331
332 manifestSummary.incrementModelAdditionCount(
333 stagedModel.getStagedModelType());
334
335 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
336 ExportImportLifecycleConstants.
337 EVENT_STAGED_MODEL_IMPORT_SUCCEEDED,
338 PortletDataContextFactoryUtil.clonePortletDataContext(
339 portletDataContext),
340 new TransientValue<T>(stagedModel));
341 }
342 catch (PortletDataException pde) {
343 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
344 ExportImportLifecycleConstants.EVENT_STAGED_MODEL_IMPORT_FAILED,
345 PortletDataContextFactoryUtil.clonePortletDataContext(
346 portletDataContext),
347 new TransientValue<T>(stagedModel), pde);
348
349 throw pde;
350 }
351 catch (Throwable t) {
352 ExportImportLifecycleManager.fireExportImportLifecycleEvent(
353 ExportImportLifecycleConstants.EVENT_STAGED_MODEL_IMPORT_FAILED,
354 PortletDataContextFactoryUtil.clonePortletDataContext(
355 portletDataContext),
356 new TransientValue<T>(stagedModel), t);
357
358 throw new PortletDataException(t);
359 }
360 }
361
362 @Override
363 public void restoreStagedModel(
364 PortletDataContext portletDataContext, T stagedModel)
365 throws PortletDataException {
366
367 try {
368 doRestoreStagedModel(portletDataContext, stagedModel);
369 }
370 catch (PortletDataException pde) {
371 throw pde;
372 }
373 catch (Exception e) {
374 throw new PortletDataException(e);
375 }
376 }
377
378 @Override
379 public boolean validateReference(
380 PortletDataContext portletDataContext, Element referenceElement) {
381
382 validateMissingGroupReference(portletDataContext, referenceElement);
383
384 String uuid = referenceElement.attributeValue("uuid");
385
386 Map<Long, Long> groupIds =
387 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
388 Group.class);
389
390 long liveGroupId = GetterUtil.getLong(
391 referenceElement.attributeValue("live-group-id"));
392
393 liveGroupId = MapUtil.getLong(groupIds, liveGroupId);
394
395 try {
396 return validateMissingReference(uuid, liveGroupId);
397 }
398 catch (Exception e) {
399 return false;
400 }
401 }
402
403 protected boolean countStagedModel(
404 PortletDataContext portletDataContext, T stagedModel) {
405
406 return !portletDataContext.isStagedModelCounted(stagedModel);
407 }
408
409 protected abstract void doExportStagedModel(
410 PortletDataContext portletDataContext, T stagedModel)
411 throws Exception;
412
413 protected void doImportMissingReference(
414 PortletDataContext portletDataContext, String uuid, long groupId,
415 long classPK)
416 throws Exception {
417
418 throw new UnsupportedOperationException();
419 }
420
421 protected abstract void doImportStagedModel(
422 PortletDataContext portletDataContext, T stagedModel)
423 throws Exception;
424
425 protected void doRestoreStagedModel(
426 PortletDataContext portletDataContext, T stagedModel)
427 throws Exception {
428
429 throw new UnsupportedOperationException();
430 }
431
432 protected void exportAssetCategories(
433 PortletDataContext portletDataContext, T stagedModel)
434 throws PortletDataException {
435
436 List<AssetCategory> assetCategories =
437 AssetCategoryLocalServiceUtil.getCategories(
438 ExportImportClassedModelUtil.getClassName(stagedModel),
439 ExportImportClassedModelUtil.getClassPK(stagedModel));
440
441 for (AssetCategory assetCategory : assetCategories) {
442 StagedModelDataHandlerUtil.exportReferenceStagedModel(
443 portletDataContext, stagedModel, assetCategory,
444 PortletDataContext.REFERENCE_TYPE_WEAK);
445 }
446 }
447
448 protected void exportComments(
449 PortletDataContext portletDataContext, T stagedModel)
450 throws PortletDataException {
451
452 if (!MapUtil.getBoolean(
453 portletDataContext.getParameterMap(),
454 PortletDataHandlerKeys.PORTLET_DATA_ALL) &&
455 !MapUtil.getBoolean(
456 portletDataContext.getParameterMap(),
457 PortletDataHandlerKeys.COMMENTS)) {
458
459 return;
460 }
461
462 MBDiscussion mbDiscussion =
463 MBDiscussionLocalServiceUtil.fetchDiscussion(
464 ExportImportClassedModelUtil.getClassName(stagedModel),
465 ExportImportClassedModelUtil.getClassPK(stagedModel));
466
467 if (mbDiscussion == null) {
468 return;
469 }
470
471 List<MBMessage> mbMessages =
472 MBMessageLocalServiceUtil.getThreadMessages(
473 mbDiscussion.getThreadId(), WorkflowConstants.STATUS_APPROVED);
474
475 if (mbMessages.isEmpty()) {
476 return;
477 }
478
479 MBMessage firstMBMessage = mbMessages.get(0);
480
481 if ((mbMessages.size() == 1) && firstMBMessage.isRoot()) {
482 return;
483 }
484
485 for (MBMessage mbMessage : mbMessages) {
486 StagedModelDataHandlerUtil.exportReferenceStagedModel(
487 portletDataContext, stagedModel, mbMessage,
488 PortletDataContext.REFERENCE_TYPE_WEAK);
489 }
490 }
491
492 protected void exportRatings(
493 PortletDataContext portletDataContext, T stagedModel)
494 throws PortletDataException {
495
496 if (!MapUtil.getBoolean(
497 portletDataContext.getParameterMap(),
498 PortletDataHandlerKeys.PORTLET_DATA_ALL) &&
499 !MapUtil.getBoolean(
500 portletDataContext.getParameterMap(),
501 PortletDataHandlerKeys.RATINGS)) {
502
503 return;
504 }
505
506 List<RatingsEntry> ratingsEntries =
507 RatingsEntryLocalServiceUtil.getEntries(
508 ExportImportClassedModelUtil.getClassName(stagedModel),
509 ExportImportClassedModelUtil.getClassPK(stagedModel));
510
511 if (ratingsEntries.isEmpty()) {
512 return;
513 }
514
515 for (RatingsEntry ratingsEntry : ratingsEntries) {
516 StagedModelDataHandlerUtil.exportReferenceStagedModel(
517 portletDataContext, stagedModel, ratingsEntry,
518 PortletDataContext.REFERENCE_TYPE_WEAK);
519 }
520 }
521
522 protected void importAssetCategories(
523 PortletDataContext portletDataContext, T stagedModel)
524 throws PortletDataException {
525
526 List<Element> referenceElements =
527 portletDataContext.getReferenceElements(
528 stagedModel, AssetCategory.class);
529
530 List<Long> assetCategoryIds = new ArrayList<Long>(
531 referenceElements.size());
532
533 for (Element referenceElement : referenceElements) {
534 long classPK = GetterUtil.getLong(
535 referenceElement.attributeValue("class-pk"));
536
537 StagedModelDataHandlerUtil.importReferenceStagedModel(
538 portletDataContext, stagedModel, AssetCategory.class, classPK);
539
540 assetCategoryIds.add(classPK);
541 }
542
543 Map<Long, Long> assetCategoryIdsMap =
544 (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
545 AssetCategory.class);
546
547 long[] importedAssetCategoryIds = new long[assetCategoryIds.size()];
548
549 for (int i = 0; i < assetCategoryIds.size(); i++) {
550 long categoryId = assetCategoryIds.get(i);
551
552 importedAssetCategoryIds[i] = MapUtil.getLong(
553 assetCategoryIdsMap, categoryId, categoryId);
554 }
555
556 portletDataContext.addAssetCategories(
557 ExportImportClassedModelUtil.getClassName(stagedModel),
558 ExportImportClassedModelUtil.getClassPK(stagedModel),
559 importedAssetCategoryIds);
560 }
561
562 protected void importComments(
563 PortletDataContext portletDataContext, T stagedModel)
564 throws PortalException {
565
566 if (!MapUtil.getBoolean(
567 portletDataContext.getParameterMap(),
568 PortletDataHandlerKeys.PORTLET_DATA_ALL) &&
569 !MapUtil.getBoolean(
570 portletDataContext.getParameterMap(),
571 PortletDataHandlerKeys.COMMENTS)) {
572
573 return;
574 }
575
576 StagedModelDataHandlerUtil.importReferenceStagedModels(
577 portletDataContext, stagedModel, MBMessage.class);
578 }
579
580 protected void importMissingGroupReference(
581 PortletDataContext portletDataContext, Element referenceElement)
582 throws PortletDataException {
583
584 StagedModelDataHandler<StagedGroup> stagedModelDataHandler =
585 (StagedModelDataHandler<StagedGroup>)
586 StagedModelDataHandlerRegistryUtil.getStagedModelDataHandler(
587 StagedGroup.class.getName());
588
589 stagedModelDataHandler.importMissingReference(
590 portletDataContext, referenceElement);
591 }
592
593 protected void importRatings(
594 PortletDataContext portletDataContext, T stagedModel)
595 throws PortalException {
596
597 if (!MapUtil.getBoolean(
598 portletDataContext.getParameterMap(),
599 PortletDataHandlerKeys.PORTLET_DATA_ALL) &&
600 !MapUtil.getBoolean(
601 portletDataContext.getParameterMap(),
602 PortletDataHandlerKeys.RATINGS)) {
603
604 return;
605 }
606
607 StagedModelDataHandlerUtil.importReferenceStagedModels(
608 portletDataContext, stagedModel, RatingsEntry.class);
609 }
610
611 protected void importReferenceStagedModels(
612 PortletDataContext portletDataContext, T stagedModel)
613 throws PortletDataException {
614
615 Element stagedModelElement =
616 portletDataContext.getImportDataStagedModelElement(stagedModel);
617
618 Element referencesElement = stagedModelElement.element("references");
619
620 if (referencesElement == null) {
621 return;
622 }
623
624 List<Element> referenceElements = referencesElement.elements();
625
626 for (Element referenceElement : referenceElements) {
627 String className = referenceElement.attributeValue("class-name");
628
629 if (className.equals(AssetCategory.class.getName()) ||
630 className.equals(RatingsEntry.class.getName()) ||
631 className.equals(MBMessage.class.getName())) {
632
633 continue;
634 }
635
636 long classPK = GetterUtil.getLong(
637 referenceElement.attributeValue("class-pk"));
638
639 StagedModelDataHandlerUtil.importReferenceStagedModel(
640 portletDataContext, stagedModel, className, classPK);
641 }
642 }
643
644 protected void validateExport(
645 PortletDataContext portletDataContext, T stagedModel)
646 throws PortletDataException {
647
648 if (stagedModel instanceof WorkflowedModel) {
649 WorkflowedModel workflowedModel = (WorkflowedModel)stagedModel;
650
651 if (!ArrayUtil.contains(
652 getExportableStatuses(), workflowedModel.getStatus())) {
653
654 PortletDataException pde = new PortletDataException(
655 PortletDataException.STATUS_UNAVAILABLE);
656
657 pde.setStagedModel(stagedModel);
658
659 throw pde;
660 }
661 }
662
663 if (stagedModel instanceof TrashedModel) {
664 TrashedModel trashedModel = (TrashedModel)stagedModel;
665
666 if (trashedModel.isInTrash()) {
667 PortletDataException pde = new PortletDataException(
668 PortletDataException.STATUS_IN_TRASH);
669
670 pde.setStagedModel(stagedModel);
671
672 throw pde;
673 }
674 }
675 }
676
677 protected boolean validateMissingGroupReference(
678 PortletDataContext portletDataContext, Element referenceElement) {
679
680 StagedModelDataHandler<StagedGroup> stagedModelDataHandler =
681 (StagedModelDataHandler<StagedGroup>)
682 StagedModelDataHandlerRegistryUtil.getStagedModelDataHandler(
683 StagedGroup.class.getName());
684
685 return stagedModelDataHandler.validateReference(
686 portletDataContext, referenceElement);
687 }
688
689 protected boolean validateMissingReference(String uuid, long groupId) {
690 T existingStagedModel = fetchMissingReference(uuid, groupId);
691
692 if (existingStagedModel == null) {
693 return false;
694 }
695
696 return true;
697 }
698
699 private static Log _log = LogFactoryUtil.getLog(
700 BaseStagedModelDataHandler.class);
701
702 }