001    /**
002     * Copyright (c) 2000-2012 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.lar.BasePortletDataHandler;
019    import com.liferay.portal.kernel.lar.PortletDataContext;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
021    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.LocaleUtil;
026    import com.liferay.portal.kernel.util.LocalizationUtil;
027    import com.liferay.portal.kernel.util.MapUtil;
028    import com.liferay.portal.kernel.util.StringBundler;
029    import com.liferay.portal.kernel.xml.Document;
030    import com.liferay.portal.kernel.xml.Element;
031    import com.liferay.portal.kernel.xml.SAXReaderUtil;
032    import com.liferay.portal.service.ServiceContext;
033    import com.liferay.portal.service.UserLocalServiceUtil;
034    import com.liferay.portal.util.PortalUtil;
035    import com.liferay.portal.util.PortletKeys;
036    import com.liferay.portlet.dynamicdatamapping.TemplateDuplicateTemplateKeyException;
037    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
038    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
039    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
040    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
041    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMStructureUtil;
042    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMTemplateUtil;
043    
044    import java.util.List;
045    import java.util.Locale;
046    import java.util.Map;
047    
048    import javax.portlet.PortletPreferences;
049    
050    /**
051     * @author Marcellus Tavares
052     */
053    public class DDMPortletDataHandlerImpl extends BasePortletDataHandler {
054    
055            public static void exportStructure(
056                            PortletDataContext portletDataContext, Element structuresElement,
057                            DDMStructure structure)
058                    throws Exception {
059    
060                    String path = getStructurePath(portletDataContext, structure);
061    
062                    if (!portletDataContext.isPathNotProcessed(path)) {
063                            return;
064                    }
065    
066                    Element structureElement = structuresElement.addElement("structure");
067    
068                    long defaultUserId = UserLocalServiceUtil.getDefaultUserId(
069                            structure.getCompanyId());
070    
071                    if (defaultUserId == structure.getUserId()) {
072                            structureElement.addAttribute("preloaded", "true");
073                    }
074    
075                    portletDataContext.addClassedModel(
076                            structureElement, path, structure, _NAMESPACE);
077            }
078    
079            public static void exportTemplate(
080                            PortletDataContext portletDataContext, Element templatesElement,
081                            DDMTemplate template)
082                    throws Exception {
083    
084                    String path = getTemplatePath(portletDataContext, template);
085    
086                    exportTemplate(portletDataContext, templatesElement, path, template);
087            }
088    
089            public static void exportTemplate(
090                            PortletDataContext portletDataContext, Element templatesElement,
091                            String path, DDMTemplate template)
092                    throws Exception {
093    
094                    if (!portletDataContext.isPathNotProcessed(path)) {
095                            return;
096                    }
097    
098                    Element templateElement = templatesElement.addElement("template");
099    
100                    portletDataContext.addClassedModel(
101                            templateElement, path, template, _NAMESPACE);
102            }
103    
104            public static void importStructure(
105                            PortletDataContext portletDataContext, Element structureElement)
106                    throws Exception {
107    
108                    String path = structureElement.attributeValue("path");
109    
110                    if (!portletDataContext.isPathNotProcessed(path)) {
111                            return;
112                    }
113    
114                    DDMStructure structure =
115                            (DDMStructure)portletDataContext.getZipEntryAsObject(
116                                    structureElement, path);
117    
118                    prepareLanguagesForImport(structure);
119    
120                    long userId = portletDataContext.getUserId(structure.getUserUuid());
121    
122                    Map<Long, Long> structureIds =
123                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
124                                    DDMStructure.class);
125    
126                    ServiceContext serviceContext = portletDataContext.createServiceContext(
127                            structureElement, structure, _NAMESPACE);
128    
129                    DDMStructure importedStructure = null;
130    
131                    if (portletDataContext.isDataStrategyMirror()) {
132                            boolean preloaded = GetterUtil.getBoolean(
133                                    structureElement.attributeValue("preloaded"));
134    
135                            DDMStructure existingStructure = null;
136    
137                            if (!preloaded) {
138                                    existingStructure = DDMStructureUtil.fetchByUUID_G(
139                                            structure.getUuid(), portletDataContext.getScopeGroupId());
140                            }
141                            else {
142                                    existingStructure = DDMStructureUtil.fetchByG_S(
143                                            portletDataContext.getScopeGroupId(),
144                                            structure.getStructureKey());
145                            }
146    
147                            if (existingStructure == null) {
148                                    serviceContext.setUuid(structure.getUuid());
149    
150                                    importedStructure = DDMStructureLocalServiceUtil.addStructure(
151                                            userId, portletDataContext.getScopeGroupId(),
152                                            structure.getParentStructureId(),
153                                            structure.getClassNameId(), structure.getStructureKey(),
154                                            structure.getNameMap(), structure.getDescriptionMap(),
155                                            structure.getXsd(), structure.getStorageType(),
156                                            structure.getType(), serviceContext);
157                            }
158                            else {
159                                    importedStructure =
160                                            DDMStructureLocalServiceUtil.updateStructure(
161                                                    existingStructure.getStructureId(),
162                                                    structure.getParentStructureId(),
163                                                    structure.getNameMap(), structure.getDescriptionMap(),
164                                                    structure.getXsd(), serviceContext);
165                            }
166                    }
167                    else {
168                            importedStructure = DDMStructureLocalServiceUtil.addStructure(
169                                    userId, portletDataContext.getScopeGroupId(),
170                                    structure.getParentStructureId(), structure.getClassNameId(),
171                                    structure.getStructureKey(), structure.getNameMap(),
172                                    structure.getDescriptionMap(), structure.getXsd(),
173                                    structure.getStorageType(), structure.getType(),
174                                    serviceContext);
175                    }
176    
177                    portletDataContext.importClassedModel(
178                            structure, importedStructure, _NAMESPACE);
179    
180                    structureIds.put(
181                            structure.getStructureId(), importedStructure.getStructureId());
182            }
183    
184            public static void importTemplate(
185                            PortletDataContext portletDataContext, Element templateElement)
186                    throws Exception {
187    
188                    String path = templateElement.attributeValue("path");
189    
190                    if (!portletDataContext.isPathNotProcessed(path)) {
191                            return;
192                    }
193    
194                    DDMTemplate template =
195                            (DDMTemplate)portletDataContext.getZipEntryAsObject(
196                                    templateElement, path);
197    
198                    long userId = portletDataContext.getUserId(template.getUserUuid());
199    
200                    Map<Long, Long> structureIds =
201                            (Map<Long, Long>)portletDataContext.getNewPrimaryKeysMap(
202                                    DDMStructure.class);
203    
204                    long classPK = MapUtil.getLong(
205                            structureIds, template.getClassPK(), template.getClassPK());
206    
207                    ServiceContext serviceContext = portletDataContext.createServiceContext(
208                            templateElement, template, _NAMESPACE);
209    
210                    DDMTemplate importedTemplate = null;
211    
212                    if (portletDataContext.isDataStrategyMirror()) {
213                            DDMTemplate existingTemplate = DDMTemplateUtil.fetchByUUID_G(
214                                    template.getUuid(), portletDataContext.getScopeGroupId());
215    
216                            if (existingTemplate == null) {
217                                    serviceContext.setUuid(template.getUuid());
218    
219                                    importedTemplate = addTemplate(
220                                            userId, portletDataContext.getScopeGroupId(), template,
221                                            classPK, serviceContext);
222                            }
223                            else {
224                                    importedTemplate = DDMTemplateLocalServiceUtil.updateTemplate(
225                                            existingTemplate.getTemplateId(), template.getNameMap(),
226                                            template.getDescriptionMap(), template.getType(),
227                                            template.getMode(), template.getLanguage(),
228                                            template.getScript(), template.isCacheable(),
229                                            serviceContext);
230                            }
231                    }
232                    else {
233                            importedTemplate = addTemplate(
234                                    userId, portletDataContext.getScopeGroupId(), template, classPK,
235                                    serviceContext);
236                    }
237    
238                    portletDataContext.importClassedModel(
239                            template, importedTemplate, _NAMESPACE);
240            }
241    
242            @Override
243            public PortletDataHandlerControl[] getExportControls() {
244                    return new PortletDataHandlerControl[] {_structures, _templates};
245            }
246    
247            @Override
248            public PortletDataHandlerControl[] getImportControls() {
249                    return new PortletDataHandlerControl[] {_structures, _templates};
250            }
251    
252            @Override
253            public boolean isAlwaysExportable() {
254                    return _ALWAYS_EXPORTABLE;
255            }
256    
257            @Override
258            public boolean isDataLocalized() {
259                    return _DATA_LOCALIZED;
260            }
261    
262            protected static DDMTemplate addTemplate(
263                            long userId, long groupId, DDMTemplate template, long classPK,
264                            ServiceContext serviceContext)
265                    throws Exception {
266    
267                    DDMTemplate newTemplate = null;
268    
269                    try {
270                            return DDMTemplateLocalServiceUtil.addTemplate(
271                                    userId, groupId, template.getClassNameId(), classPK,
272                                    template.getTemplateKey(), template.getNameMap(),
273                                    template.getDescriptionMap(), template.getType(),
274                                    template.getMode(), template.getLanguage(),
275                                    template.getScript(), template.isCacheable(), serviceContext);
276                    }
277                    catch (TemplateDuplicateTemplateKeyException tdtke) {
278                            newTemplate = DDMTemplateLocalServiceUtil.addTemplate(
279                                    userId, groupId, template.getClassNameId(), classPK, null,
280                                    template.getNameMap(), template.getDescriptionMap(),
281                                    template.getType(), template.getMode(), template.getLanguage(),
282                                    template.getScript(), template.isCacheable(), serviceContext);
283    
284                            if (_log.isWarnEnabled()) {
285                                    _log.warn(
286                                            "A template with the key " + template.getTemplateKey() +
287                                                    " already exists. The new generated key is " +
288                                                            newTemplate.getTemplateKey());
289                            }
290                    }
291    
292                    return newTemplate;
293            }
294    
295            protected static String getStructurePath(
296                    PortletDataContext portletDataContext, DDMStructure structure) {
297    
298                    StringBundler sb = new StringBundler(4);
299    
300                    sb.append(
301                            portletDataContext.getPortletPath(
302                                    PortletKeys.DYNAMIC_DATA_MAPPING));
303                    sb.append("/structures/");
304                    sb.append(structure.getStructureId());
305                    sb.append(".xml");
306    
307                    return sb.toString();
308            }
309    
310            protected static String getTemplatePath(
311                    PortletDataContext portletDataContext, DDMTemplate template) {
312    
313                    StringBundler sb = new StringBundler(4);
314    
315                    sb.append(
316                            portletDataContext.getPortletPath(
317                                    PortletKeys.DYNAMIC_DATA_MAPPING));
318                    sb.append("/templates/");
319                    sb.append(template.getTemplateId());
320                    sb.append(".xml");
321    
322                    return sb.toString();
323            }
324    
325            protected static void prepareLanguagesForImport(DDMStructure structure)
326                    throws PortalException {
327    
328                    Locale structureDefaultLocale = LocaleUtil.fromLanguageId(
329                            structure.getDefaultLanguageId());
330    
331                    Locale[] structureAvailableLocales = LocaleUtil.fromLanguageIds(
332                            structure.getAvailableLanguageIds());
333    
334                    Locale defaultImportLocale = LocalizationUtil.getDefaultImportLocale(
335                            DDMStructure.class.getName(), structure.getPrimaryKey(),
336                            structureDefaultLocale, structureAvailableLocales);
337    
338                    structure.prepareLocalizedFieldsForImport(defaultImportLocale);
339            }
340    
341            @Override
342            protected PortletPreferences doDeleteData(
343                            PortletDataContext portletDataContext, String portletId,
344                            PortletPreferences portletPreferences)
345                    throws Exception {
346    
347                    if (!portletDataContext.addPrimaryKey(
348                                    DDMPortletDataHandlerImpl.class, "deleteData")) {
349    
350                            DDMTemplateLocalServiceUtil.deleteTemplates(
351                                    portletDataContext.getScopeGroupId());
352    
353                            DDMStructureLocalServiceUtil.deleteStructures(
354                                    portletDataContext.getScopeGroupId());
355                    }
356    
357                    return portletPreferences;
358            }
359    
360            @Override
361            protected String doExportData(
362                            PortletDataContext portletDataContext, String portletId,
363                            PortletPreferences portletPreferences)
364                    throws Exception {
365    
366                    portletDataContext.addPermissions(
367                            "com.liferay.portlet.dynamicdatamapping",
368                            portletDataContext.getScopeGroupId());
369    
370                    Document document = SAXReaderUtil.createDocument();
371    
372                    Element rootElement = document.addElement("ddm-data");
373    
374                    rootElement.addAttribute(
375                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
376    
377                    Element structuresElement = rootElement.addElement("structures");
378    
379                    List<DDMStructure> ddmStructures = DDMStructureUtil.findByGroupId(
380                            portletDataContext.getScopeGroupId());
381    
382                    for (DDMStructure structure : ddmStructures) {
383                            if (portletDataContext.isWithinDateRange(
384                                            structure.getModifiedDate())) {
385    
386                                    exportStructure(
387                                            portletDataContext, structuresElement, structure);
388                            }
389                    }
390    
391                    Element templatesElement = rootElement.addElement("templates");
392    
393                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "templates")) {
394                            List<DDMTemplate> templates = DDMTemplateUtil.findByG_C(
395                                    portletDataContext.getScopeGroupId(),
396                                    PortalUtil.getClassNameId(DDMStructure.class));
397    
398                            for (DDMTemplate template : templates) {
399                                    if (portletDataContext.isWithinDateRange(
400                                                    template.getModifiedDate())) {
401    
402                                            exportTemplate(
403                                                    portletDataContext, templatesElement, template);
404                                    }
405                            }
406                    }
407    
408                    return document.formattedString();
409            }
410    
411            @Override
412            protected PortletPreferences doImportData(
413                            PortletDataContext portletDataContext, String portletId,
414                            PortletPreferences portletPreferences, String data)
415                    throws Exception {
416    
417                    portletDataContext.importPermissions(
418                            "com.liferay.portlet.dynamicdatamapping",
419                            portletDataContext.getSourceGroupId(),
420                            portletDataContext.getScopeGroupId());
421    
422                    Document document = SAXReaderUtil.read(data);
423    
424                    Element rootElement = document.getRootElement();
425    
426                    Element structuresElement = rootElement.element("structures");
427    
428                    List<Element> structureElements = structuresElement.elements(
429                            "structure");
430    
431                    for (Element structureElement : structureElements) {
432                            importStructure(portletDataContext, structureElement);
433                    }
434    
435                    if (portletDataContext.getBooleanParameter(_NAMESPACE, "templates")) {
436                            Element templatesElement = rootElement.element("templates");
437    
438                            List<Element> templateElements = templatesElement.elements(
439                                    "template");
440    
441                            for (Element templateElement : templateElements) {
442                                    importTemplate(portletDataContext, templateElement);
443                            }
444                    }
445    
446                    return portletPreferences;
447            }
448    
449            private static final boolean _ALWAYS_EXPORTABLE = true;
450    
451            private static final boolean _DATA_LOCALIZED = true;
452    
453            private static final String _NAMESPACE = "ddm";
454    
455            private static Log _log = LogFactoryUtil.getLog(
456                    DDMPortletDataHandlerImpl.class);
457    
458            private static PortletDataHandlerBoolean _structures =
459                    new PortletDataHandlerBoolean(_NAMESPACE, "structures", true, true);
460    
461            private static PortletDataHandlerBoolean _templates =
462                    new PortletDataHandlerBoolean(_NAMESPACE, "templates");
463    
464    }