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.ExportImportHelperUtil;
021    import com.liferay.portal.kernel.lar.ExportImportPathUtil;
022    import com.liferay.portal.kernel.lar.PortletDataContext;
023    import com.liferay.portal.kernel.lar.PortletDataException;
024    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.LocaleUtil;
030    import com.liferay.portal.kernel.util.LocalizationUtil;
031    import com.liferay.portal.kernel.util.MapUtil;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.xml.Element;
036    import com.liferay.portal.model.Image;
037    import com.liferay.portal.service.ImageLocalServiceUtil;
038    import com.liferay.portal.service.ServiceContext;
039    import com.liferay.portal.service.UserLocalServiceUtil;
040    import com.liferay.portal.util.PortalUtil;
041    import com.liferay.portlet.dynamicdatamapping.TemplateDuplicateTemplateKeyException;
042    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
043    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
044    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
045    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
046    
047    import java.io.File;
048    
049    import java.util.HashMap;
050    import java.util.Locale;
051    import java.util.Map;
052    
053    /**
054     * @author Mate Thurzo
055     * @author Daniel Kocsis
056     */
057    public class DDMTemplateStagedModelDataHandler
058            extends BaseStagedModelDataHandler<DDMTemplate> {
059    
060            public static final String[] CLASS_NAMES = {DDMTemplate.class.getName()};
061    
062            @Override
063            public void deleteStagedModel(
064                            String uuid, long groupId, String className, String extraData)
065                    throws PortalException, SystemException {
066    
067                    DDMTemplate ddmTemplate =
068                            DDMTemplateLocalServiceUtil.fetchDDMTemplateByUuidAndGroupId(
069                                    uuid, groupId);
070    
071                    if (ddmTemplate != null) {
072                            DDMTemplateLocalServiceUtil.deleteTemplate(ddmTemplate);
073                    }
074            }
075    
076            @Override
077            public String[] getClassNames() {
078                    return CLASS_NAMES;
079            }
080    
081            @Override
082            public String getDisplayName(DDMTemplate template) {
083                    return template.getNameCurrentValue();
084            }
085    
086            @Override
087            public Map<String, String> getReferenceAttributes(
088                    PortletDataContext portletDataContext, DDMTemplate template) {
089    
090                    Map<String, String> referenceAttributes = new HashMap<String, String>();
091    
092                    referenceAttributes.put(
093                            "referenced-class-name", template.getClassName());
094                    referenceAttributes.put("template-key", template.getTemplateKey());
095    
096                    long defaultUserId = 0;
097    
098                    try {
099                            defaultUserId = UserLocalServiceUtil.getDefaultUserId(
100                                    template.getCompanyId());
101                    }
102                    catch (Exception e) {
103                            return referenceAttributes;
104                    }
105    
106                    boolean preloaded = false;
107    
108                    if (defaultUserId == template.getUserId()) {
109                            preloaded = true;
110                    }
111    
112                    referenceAttributes.put("preloaded", String.valueOf(preloaded));
113    
114                    return referenceAttributes;
115            }
116    
117            @Override
118            public void importCompanyStagedModel(
119                            PortletDataContext portletDataContext, Element element)
120                    throws PortletDataException {
121    
122                    String uuid = element.attributeValue("uuid");
123                    long classNameId = PortalUtil.getClassNameId(
124                            element.attributeValue("referenced-class-name"));
125                    String templateKey = element.attributeValue("template-key");
126                    boolean preloaded = GetterUtil.getBoolean(
127                            element.attributeValue("preloaded"));
128    
129                    DDMTemplate existingTemplate = null;
130    
131                    try {
132                            existingTemplate = getExistingTemplate(
133                                    uuid, portletDataContext.getCompanyGroupId(), classNameId,
134                                    templateKey, preloaded);
135                    }
136                    catch (Exception e) {
137                            throw new PortletDataException(e);
138                    }
139    
140                    Map<Long, Long> templateIds =
141                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
142                                    DDMTemplate.class);
143    
144                    long templateId = GetterUtil.getLong(
145                            element.attributeValue("class-pk"));
146    
147                    templateIds.put(templateId, existingTemplate.getTemplateId());
148    
149                    Map<String, String> templateKeys =
150                            (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
151                                    DDMTemplate.class + ".ddmTemplateKey");
152    
153                    templateKeys.put(templateKey, existingTemplate.getTemplateKey());
154            }
155    
156            @Override
157            public boolean validateReference(
158                    PortletDataContext portletDataContext, Element referenceElement) {
159    
160                    String uuid = referenceElement.attributeValue("uuid");
161                    long classNameId = PortalUtil.getClassNameId(
162                            referenceElement.attributeValue("referenced-class-name"));
163                    String templateKey = referenceElement.attributeValue("template-key");
164                    boolean preloaded = GetterUtil.getBoolean(
165                            referenceElement.attributeValue("preloaded"));
166    
167                    try {
168                            DDMTemplate existingTemplate = getExistingTemplate(
169                                    uuid, portletDataContext.getScopeGroupId(), classNameId,
170                                    templateKey, preloaded);
171    
172                            if (existingTemplate == null) {
173                                    existingTemplate = getExistingTemplate(
174                                            uuid, portletDataContext.getCompanyGroupId(), classNameId,
175                                            templateKey, preloaded);
176                            }
177    
178                            if (existingTemplate == null) {
179                                    return false;
180                            }
181    
182                            return true;
183                    }
184                    catch (Exception e) {
185                            return false;
186                    }
187            }
188    
189            protected DDMTemplate addTemplate(
190                            long userId, long groupId, DDMTemplate template, long classPK,
191                            File smallFile, ServiceContext serviceContext)
192                    throws Exception {
193    
194                    DDMTemplate newTemplate = null;
195    
196                    try {
197                            return DDMTemplateLocalServiceUtil.addTemplate(
198                                    userId, groupId, template.getClassNameId(), classPK,
199                                    template.getTemplateKey(), template.getNameMap(),
200                                    template.getDescriptionMap(), template.getType(),
201                                    template.getMode(), template.getLanguage(),
202                                    template.getScript(), template.isCacheable(),
203                                    template.isSmallImage(), template.getSmallImageURL(), smallFile,
204                                    serviceContext);
205                    }
206                    catch (TemplateDuplicateTemplateKeyException tdtke) {
207                            newTemplate = DDMTemplateLocalServiceUtil.addTemplate(
208                                    userId, groupId, template.getClassNameId(), classPK, null,
209                                    template.getNameMap(), template.getDescriptionMap(),
210                                    template.getType(), template.getMode(), template.getLanguage(),
211                                    template.getScript(), template.isCacheable(),
212                                    template.isSmallImage(), template.getSmallImageURL(), smallFile,
213                                    serviceContext);
214    
215                            if (_log.isWarnEnabled()) {
216                                    StringBundler sb = new StringBundler(4);
217    
218                                    sb.append("A template with the key ");
219                                    sb.append(template.getTemplateKey());
220                                    sb.append(" already exists. The new generated key is ");
221                                    sb.append(newTemplate.getTemplateKey());
222    
223                                    _log.warn(sb.toString());
224                            }
225                    }
226    
227                    return newTemplate;
228            }
229    
230            @Override
231            protected void doExportStagedModel(
232                            PortletDataContext portletDataContext, DDMTemplate template)
233                    throws Exception {
234    
235                    Element templateElement = portletDataContext.getExportDataElement(
236                            template);
237    
238                    DDMStructure structure = DDMStructureLocalServiceUtil.fetchStructure(
239                            template.getClassPK());
240    
241                    if (structure != null) {
242                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
243                                    portletDataContext, template, structure,
244                                    PortletDataContext.REFERENCE_TYPE_STRONG);
245                    }
246    
247                    if (template.isSmallImage()) {
248                            Image smallImage = ImageLocalServiceUtil.fetchImage(
249                                    template.getSmallImageId());
250    
251                            if (Validator.isNotNull(template.getSmallImageURL())) {
252                                    String smallImageURL =
253                                            ExportImportHelperUtil.replaceExportContentReferences(
254                                                    portletDataContext, template, templateElement,
255                                                    template.getSmallImageURL().concat(StringPool.SPACE),
256                                                    true);
257    
258                                    template.setSmallImageURL(smallImageURL);
259                            }
260                            else if (smallImage != null) {
261                                    String smallImagePath = ExportImportPathUtil.getModelPath(
262                                            template,
263                                            smallImage.getImageId() + StringPool.PERIOD +
264                                                    template.getSmallImageType());
265    
266                                    templateElement.addAttribute(
267                                            "small-image-path", smallImagePath);
268    
269                                    template.setSmallImageType(smallImage.getType());
270    
271                                    portletDataContext.addZipEntry(
272                                            smallImagePath, smallImage.getTextObj());
273                            }
274                    }
275    
276                    String script = ExportImportHelperUtil.replaceExportContentReferences(
277                            portletDataContext, template, templateElement, template.getScript(),
278                            portletDataContext.getBooleanParameter(
279                                    DDMPortletDataHandler.NAMESPACE, "referenced-content"));
280    
281                    template.setScript(script);
282    
283                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
284                            template.getCompanyId());
285    
286                    if (defaultUserId == template.getUserId()) {
287                            templateElement.addAttribute("preloaded", "true");
288                    }
289    
290                    portletDataContext.addClassedModel(
291                            templateElement, ExportImportPathUtil.getModelPath(template),
292                            template);
293            }
294    
295            @Override
296            protected void doImportStagedModel(
297                            PortletDataContext portletDataContext, DDMTemplate template)
298                    throws Exception {
299    
300                    prepareLanguagesForImport(template);
301    
302                    long userId = portletDataContext.getUserId(template.getUserUuid());
303    
304                    long classPK = template.getClassPK();
305    
306                    if (classPK > 0) {
307                            StagedModelDataHandlerUtil.importReferenceStagedModel(
308                                    portletDataContext, template, DDMStructure.class, classPK);
309    
310                            Map<Long, Long> structureIds =
311                                    (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
312                                            DDMStructure.class);
313    
314                            classPK = MapUtil.getLong(structureIds, classPK, classPK);
315                    }
316    
317                    File smallFile = null;
318    
319                    try {
320                            Element templateElement =
321                                    portletDataContext.getImportDataStagedModelElement(template);
322    
323                            if (template.isSmallImage()) {
324                                    String smallImagePath = templateElement.attributeValue(
325                                            "small-image-path");
326    
327                                    if (Validator.isNotNull(template.getSmallImageURL())) {
328                                            String smallImageURL =
329                                                    ExportImportHelperUtil.replaceImportContentReferences(
330                                                            portletDataContext, templateElement,
331                                                            template.getSmallImageURL(), true);
332    
333                                            template.setSmallImageURL(smallImageURL);
334                                    }
335                                    else if (Validator.isNotNull(smallImagePath)) {
336                                            byte[] bytes = portletDataContext.getZipEntryAsByteArray(
337                                                    smallImagePath);
338    
339                                            if (bytes != null) {
340                                                    smallFile = FileUtil.createTempFile(
341                                                            template.getSmallImageType());
342    
343                                                    FileUtil.write(smallFile, bytes);
344                                            }
345                                    }
346                            }
347    
348                            String script =
349                                    ExportImportHelperUtil.replaceImportContentReferences(
350                                            portletDataContext, templateElement, template.getScript(),
351                                            true);
352    
353                            template.setScript(script);
354    
355                            ServiceContext serviceContext =
356                                    portletDataContext.createServiceContext(template);
357    
358                            DDMTemplate importedTemplate = null;
359    
360                            if (portletDataContext.isDataStrategyMirror()) {
361                                    boolean preloaded = GetterUtil.getBoolean(
362                                            templateElement.attributeValue("preloaded"));
363    
364                                    DDMTemplate existingTemplate = getExistingTemplate(
365                                            template.getUuid(), portletDataContext.getScopeGroupId(),
366                                            template.getClassNameId(), template.getTemplateKey(),
367                                            preloaded);
368    
369                                    if (existingTemplate == null) {
370                                            serviceContext.setUuid(template.getUuid());
371    
372                                            importedTemplate = addTemplate(
373                                                    userId, portletDataContext.getScopeGroupId(), template,
374                                                    classPK, smallFile, serviceContext);
375                                    }
376                                    else {
377                                            importedTemplate =
378                                                    DDMTemplateLocalServiceUtil.updateTemplate(
379                                                            existingTemplate.getTemplateId(),
380                                                            template.getClassPK(), template.getNameMap(),
381                                                            template.getDescriptionMap(), template.getType(),
382                                                            template.getMode(), template.getLanguage(),
383                                                            template.getScript(), template.isCacheable(),
384                                                            template.isSmallImage(),
385                                                            template.getSmallImageURL(), smallFile,
386                                                            serviceContext);
387                                    }
388                            }
389                            else {
390                                    importedTemplate = addTemplate(
391                                            userId, portletDataContext.getScopeGroupId(), template,
392                                            classPK, smallFile, serviceContext);
393                            }
394    
395                            portletDataContext.importClassedModel(template, importedTemplate);
396    
397                            Map<String, String> ddmTemplateKeys =
398                                    (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
399                                            DDMTemplate.class + ".ddmTemplateKey");
400    
401                            ddmTemplateKeys.put(
402                                    template.getTemplateKey(), importedTemplate.getTemplateKey());
403                    }
404                    finally {
405                            if (smallFile != null) {
406                                    smallFile.delete();
407                            }
408                    }
409            }
410    
411            protected DDMTemplate getExistingTemplate(
412                            String uuid, long groupId, long classNameId, String templateKey,
413                            boolean preloaded)
414                    throws Exception {
415    
416                    DDMTemplate existingTemplate = null;
417    
418                    if (!preloaded) {
419                            existingTemplate =
420                                    DDMTemplateLocalServiceUtil.fetchDDMTemplateByUuidAndGroupId(
421                                            uuid, groupId);
422                    }
423                    else {
424                            existingTemplate = DDMTemplateLocalServiceUtil.fetchTemplate(
425                                    groupId, classNameId, templateKey);
426                    }
427    
428                    return existingTemplate;
429            }
430    
431            protected void prepareLanguagesForImport(DDMTemplate template)
432                    throws PortalException {
433    
434                    Locale defaultLocale = LocaleUtil.fromLanguageId(
435                            template.getDefaultLanguageId());
436    
437                    Locale[] availableLocales = LocaleUtil.fromLanguageIds(
438                            template.getAvailableLanguageIds());
439    
440                    Locale defaultImportLocale = LocalizationUtil.getDefaultImportLocale(
441                            DDMTemplate.class.getName(), template.getPrimaryKey(),
442                            defaultLocale, availableLocales);
443    
444                    template.prepareLocalizedFieldsForImport(defaultImportLocale);
445            }
446    
447            private static Log _log = LogFactoryUtil.getLog(
448                    DDMTemplateStagedModelDataHandler.class);
449    
450    }