001    /**
002     * Copyright (c) 2000-2013 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.portlet.dynamicdatamapping.lar;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.lar.BaseStagedModelDataHandler;
020    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
021    import com.liferay.portal.kernel.lar.PortletDataContext;
022    import com.liferay.portal.kernel.lar.PortletDataException;
023    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
024    import com.liferay.portal.kernel.log.Log;
025    import com.liferay.portal.kernel.log.LogFactoryUtil;
026    import com.liferay.portal.kernel.util.DateUtil;
027    import com.liferay.portal.kernel.util.GetterUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.LocalizationUtil;
030    import com.liferay.portal.kernel.util.MapUtil;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.service.ServiceContext;
034    import com.liferay.portal.service.UserLocalServiceUtil;
035    import com.liferay.portal.util.PortalUtil;
036    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
037    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
038    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
039    
040    import java.util.HashMap;
041    import java.util.Locale;
042    import java.util.Map;
043    
044    /**
045     * @author Mate Thurzo
046     * @author Daniel Kocsis
047     */
048    public class DDMStructureStagedModelDataHandler
049            extends BaseStagedModelDataHandler<DDMStructure> {
050    
051            public static final String[] CLASS_NAMES = {DDMStructure.class.getName()};
052    
053            @Override
054            public void deleteStagedModel(
055                            String uuid, long groupId, String className, String extraData)
056                    throws PortalException, SystemException {
057    
058                    DDMStructure ddmStructure =
059                            DDMStructureLocalServiceUtil.fetchDDMStructureByUuidAndGroupId(
060                                    uuid, groupId);
061    
062                    if (ddmStructure != null) {
063                            DDMStructureLocalServiceUtil.deleteStructure(ddmStructure);
064                    }
065            }
066    
067            @Override
068            public String[] getClassNames() {
069                    return CLASS_NAMES;
070            }
071    
072            @Override
073            public String getDisplayName(DDMStructure structure) {
074                    return structure.getNameCurrentValue();
075            }
076    
077            @Override
078            public Map<String, String> getReferenceAttributes(
079                    PortletDataContext portletDataContext, DDMStructure structure) {
080    
081                    Map<String, String> referenceAttributes = new HashMap<String, String>();
082    
083                    referenceAttributes.put(
084                            "referenced-class-name", structure.getClassName());
085                    referenceAttributes.put("structure-key", structure.getStructureKey());
086    
087                    long defaultUserId = 0;
088    
089                    try {
090                            defaultUserId = UserLocalServiceUtil.getDefaultUserId(
091                                    structure.getCompanyId());
092                    }
093                    catch (Exception e) {
094                            return referenceAttributes;
095                    }
096    
097                    boolean preloaded = false;
098    
099                    if (defaultUserId == structure.getUserId()) {
100                            preloaded = true;
101                    }
102    
103                    referenceAttributes.put("preloaded", String.valueOf(preloaded));
104    
105                    return referenceAttributes;
106            }
107    
108            @Override
109            public void importCompanyStagedModel(
110                            PortletDataContext portletDataContext, Element element)
111                    throws PortletDataException {
112    
113                    String uuid = element.attributeValue("uuid");
114                    long classNameId = PortalUtil.getClassNameId(
115                            element.attributeValue("referenced-class-name"));
116                    String structureKey = element.attributeValue("structure-key");
117                    boolean preloaded = GetterUtil.getBoolean(
118                            element.attributeValue("preloaded"));
119    
120                    DDMStructure existingStructure = null;
121    
122                    try {
123                            existingStructure = getExistingStructure(
124                                    uuid, portletDataContext.getCompanyGroupId(), classNameId,
125                                    structureKey, preloaded);
126                    }
127                    catch (Exception e) {
128                            throw new PortletDataException(e);
129                    }
130    
131                    Map<Long, Long> structureIds =
132                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
133                                    DDMStructure.class);
134    
135                    long structureId = GetterUtil.getLong(
136                            element.attributeValue("class-pk"));
137    
138                    structureIds.put(structureId, existingStructure.getStructureId());
139    
140                    Map<String, String> structureKeys =
141                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
142                                    DDMStructure.class + ".ddmStructureKey");
143    
144                    structureKeys.put(structureKey, existingStructure.getStructureKey());
145    
146                    Map<Long, Long> structureIdsUnmodified =
147                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
148                                    DDMStructure.class + ".unmodified");
149    
150                    structureIdsUnmodified.put(
151                            structureId, existingStructure.getStructureId());
152            }
153    
154            @Override
155            public boolean validateReference(
156                    PortletDataContext portletDataContext, Element referenceElement) {
157    
158                    String uuid = referenceElement.attributeValue("uuid");
159                    long classNameId = PortalUtil.getClassNameId(
160                            referenceElement.attributeValue("referenced-class-name"));
161                    String structureKey = referenceElement.attributeValue("structure-key");
162                    boolean preloaded = GetterUtil.getBoolean(
163                            referenceElement.attributeValue("preloaded"));
164    
165                    try {
166                            DDMStructure existingStructure = getExistingStructure(
167                                    uuid, portletDataContext.getScopeGroupId(), classNameId,
168                                    structureKey, preloaded);
169    
170                            if (existingStructure == null) {
171                                    existingStructure = getExistingStructure(
172                                            uuid, portletDataContext.getCompanyGroupId(), classNameId,
173                                            structureKey, preloaded);
174                            }
175    
176                            if (existingStructure == null) {
177                                    return false;
178                            }
179    
180                            return true;
181                    }
182                    catch (Exception e) {
183                            return false;
184                    }
185            }
186    
187            @Override
188            protected void doExportStagedModel(
189                            PortletDataContext portletDataContext, DDMStructure structure)
190                    throws Exception {
191    
192                    Element structureElement = portletDataContext.getExportDataElement(
193                            structure);
194    
195                    if (structure.getParentStructureId() !=
196                                    DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID) {
197    
198                            DDMStructure parentStructure =
199                                    DDMStructureLocalServiceUtil.getStructure(
200                                            structure.getParentStructureId());
201    
202                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
203                                    portletDataContext, structure, parentStructure,
204                                    PortletDataContext.REFERENCE_TYPE_PARENT);
205                    }
206    
207                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
208                            structure.getCompanyId());
209    
210                    if (defaultUserId == structure.getUserId()) {
211                            structureElement.addAttribute("preloaded", "true");
212                    }
213    
214                    portletDataContext.addClassedModel(
215                            structureElement, ExportImportPathUtil.getModelPath(structure),
216                            structure);
217            }
218    
219            @Override
220            protected void doImportStagedModel(
221                            PortletDataContext portletDataContext, DDMStructure structure)
222                    throws Exception {
223    
224                    prepareLanguagesForImport(structure);
225    
226                    long userId = portletDataContext.getUserId(structure.getUserUuid());
227    
228                    if (structure.getParentStructureId() !=
229                                    DDMStructureConstants.DEFAULT_PARENT_STRUCTURE_ID) {
230    
231                            StagedModelDataHandlerUtil.importReferenceStagedModel(
232                                    portletDataContext, structure, DDMStructure.class,
233                                    structure.getParentStructureId());
234                    }
235    
236                    Map<Long, Long> structureIds =
237                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
238                                    DDMStructure.class);
239    
240                    long parentStructureId = MapUtil.getLong(
241                            structureIds, structure.getParentStructureId(),
242                            structure.getParentStructureId());
243    
244                    Map<String, String> structureKeys =
245                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
246                                    DDMStructure.class + ".ddmStructureKey");
247    
248                    ServiceContext serviceContext = portletDataContext.createServiceContext(
249                            structure);
250    
251                    DDMStructure importedStructure = null;
252    
253                    if (portletDataContext.isDataStrategyMirror()) {
254                            Element element =
255                                    portletDataContext.getImportDataStagedModelElement(structure);
256    
257                            boolean preloaded = GetterUtil.getBoolean(
258                                    element.attributeValue("preloaded"));
259    
260                            DDMStructure existingStructure = getExistingStructure(
261                                    structure.getUuid(), portletDataContext.getScopeGroupId(),
262                                    structure.getClassNameId(), structure.getStructureKey(),
263                                    preloaded);
264    
265                            if (existingStructure == null) {
266                                    serviceContext.setUuid(structure.getUuid());
267    
268                                    importedStructure = DDMStructureLocalServiceUtil.addStructure(
269                                            userId, portletDataContext.getScopeGroupId(),
270                                            parentStructureId, structure.getClassNameId(),
271                                            structure.getStructureKey(), structure.getNameMap(),
272                                            structure.getDescriptionMap(), structure.getXsd(),
273                                            structure.getStorageType(), structure.getType(),
274                                            serviceContext);
275                            }
276                            else if (isModifiedStructure(existingStructure, structure)) {
277                                    importedStructure =
278                                            DDMStructureLocalServiceUtil.updateStructure(
279                                                    existingStructure.getStructureId(), parentStructureId,
280                                                    structure.getNameMap(), structure.getDescriptionMap(),
281                                                    structure.getXsd(), serviceContext);
282                            }
283                            else {
284                                    if (_log.isDebugEnabled()) {
285                                            _log.debug(
286                                                    "Not importing DDM structure with key " +
287                                                            structure.getStructureKey() +
288                                                                    " since it was not modified");
289                                    }
290    
291                                    importedStructure = existingStructure;
292    
293                                    Map<Long, Long> structureIdsUnmodified =
294                                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
295                                                    DDMStructure.class + ".unmodified");
296    
297                                    structureIdsUnmodified.put(
298                                            structure.getStructureId(),
299                                            existingStructure.getStructureId());
300                            }
301                    }
302                    else {
303                            importedStructure = DDMStructureLocalServiceUtil.addStructure(
304                                    userId, portletDataContext.getScopeGroupId(), parentStructureId,
305                                    structure.getClassNameId(), null, structure.getNameMap(),
306                                    structure.getDescriptionMap(), structure.getXsd(),
307                                    structure.getStorageType(), structure.getType(),
308                                    serviceContext);
309                    }
310    
311                    portletDataContext.importClassedModel(structure, importedStructure);
312    
313                    structureKeys.put(
314                            structure.getStructureKey(), importedStructure.getStructureKey());
315            }
316    
317            protected boolean isModifiedStructure(
318                    DDMStructure existingStructure, DDMStructure structure) {
319    
320                    if (DateUtil.compareTo(
321                                    structure.getModifiedDate(),
322                                    existingStructure.getModifiedDate()) > 0) {
323    
324                            return true;
325                    }
326    
327                    if (!Validator.equals(
328                                    structure.getNameMap(), existingStructure.getNameMap())) {
329    
330                            return true;
331                    }
332    
333                    if (!Validator.equals(
334                                    structure.getDescriptionMap(),
335                                    existingStructure.getDescriptionMap())) {
336    
337                            return true;
338                    }
339    
340                    if (!Validator.equals(structure.getXsd(), existingStructure.getXsd())) {
341                            return true;
342                    }
343    
344                    if (!Validator.equals(
345                                    structure.getStorageType(),
346                                    existingStructure.getStorageType())) {
347    
348                            return true;
349                    }
350    
351                    if (!Validator.equals(
352                                    structure.getType(), existingStructure.getType())) {
353    
354                            return true;
355                    }
356    
357                    return false;
358            }
359    
360            protected DDMStructure getExistingStructure(
361                            String uuid, long groupId, long classNameId, String structureKey,
362                            boolean preloaded)
363                    throws Exception {
364    
365                    DDMStructure existingStructure = null;
366    
367                    if (!preloaded) {
368                            existingStructure =
369                                    DDMStructureLocalServiceUtil.fetchDDMStructureByUuidAndGroupId(
370                                            uuid, groupId);
371                    }
372                    else {
373                            existingStructure = DDMStructureLocalServiceUtil.fetchStructure(
374                                    groupId, classNameId, structureKey);
375                    }
376    
377                    return existingStructure;
378            }
379    
380            protected void prepareLanguagesForImport(DDMStructure structure)
381                    throws PortalException {
382    
383                    Locale defaultLocale = LocaleUtil.fromLanguageId(
384                            structure.getDefaultLanguageId());
385    
386                    Locale[] availableLocales = LocaleUtil.fromLanguageIds(
387                            structure.getAvailableLanguageIds());
388    
389                    Locale defaultImportLocale = LocalizationUtil.getDefaultImportLocale(
390                            DDMStructure.class.getName(), structure.getPrimaryKey(),
391                            defaultLocale, availableLocales);
392    
393                    structure.prepareLocalizedFieldsForImport(defaultImportLocale);
394            }
395    
396            private static Log _log = LogFactoryUtil.getLog(
397                    DDMStructureStagedModelDataHandler.class);
398    
399    }