001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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    /**
051     * @author Mate Thurzo
052     * @author Daniel Kocsis
053     * @author Zsolt Berentey
054     */
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                    // Try to fetch the existing staged model from the importing group
141    
142                    T existingStagedModel = fetchStagedModelByUuidAndGroupId(uuid, groupId);
143    
144                    if (existingStagedModel != null) {
145                            return existingStagedModel;
146                    }
147    
148                    try {
149    
150                            // Try to fetch the existing staged model from the parent sites
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            /**
218             * @deprecated As of 7.0.0, replaced by {@link
219             *             #importMissingReference(PortletDataContext, Element)}
220             */
221            @Deprecated
222            @Override
223            public void importCompanyStagedModel(
224                            PortletDataContext portletDataContext, Element referenceElement)
225                    throws PortletDataException {
226    
227                    importMissingReference(portletDataContext, referenceElement);
228            }
229    
230            /**
231             * @deprecated As of 7.0.0, replaced by {@link
232             *             #importMissingReference(PortletDataContext, String, long,
233             *             long)}
234             */
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    }