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.portlet.dynamicdatamapping.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.systemevent.SystemEvent;
021    import com.liferay.portal.kernel.template.TemplateConstants;
022    import com.liferay.portal.kernel.util.Constants;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.LocaleUtil;
026    import com.liferay.portal.kernel.util.OrderByComparator;
027    import com.liferay.portal.kernel.util.PropsKeys;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.workflow.WorkflowConstants;
032    import com.liferay.portal.model.Image;
033    import com.liferay.portal.model.ResourceConstants;
034    import com.liferay.portal.model.SystemEventConstants;
035    import com.liferay.portal.model.User;
036    import com.liferay.portal.service.ServiceContext;
037    import com.liferay.portal.service.persistence.ImageUtil;
038    import com.liferay.portal.util.PortalUtil;
039    import com.liferay.portal.util.PrefsPropsUtil;
040    import com.liferay.portlet.dynamicdatamapping.InvalidTemplateVersionException;
041    import com.liferay.portlet.dynamicdatamapping.NoSuchTemplateException;
042    import com.liferay.portlet.dynamicdatamapping.RequiredTemplateException;
043    import com.liferay.portlet.dynamicdatamapping.TemplateDuplicateTemplateKeyException;
044    import com.liferay.portlet.dynamicdatamapping.TemplateNameException;
045    import com.liferay.portlet.dynamicdatamapping.TemplateScriptException;
046    import com.liferay.portlet.dynamicdatamapping.TemplateSmallImageNameException;
047    import com.liferay.portlet.dynamicdatamapping.TemplateSmallImageSizeException;
048    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
049    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
050    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateVersion;
051    import com.liferay.portlet.dynamicdatamapping.service.base.DDMTemplateLocalServiceBaseImpl;
052    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
053    
054    import java.io.File;
055    import java.io.IOException;
056    
057    import java.util.ArrayList;
058    import java.util.List;
059    import java.util.Locale;
060    import java.util.Map;
061    
062    /**
063     * Provides the local service for accessing, adding, copying, deleting, and
064     * updating dynamic data mapping (DDM) templates.
065     *
066     * <p>
067     * DDM templates (templates) are used in Liferay to render templated content
068     * like applications, forms, dynamic data lists, or web contents.
069     * </p>
070     *
071     * <p>
072     * Templates support a variety of templating languages, like Velocity or
073     * FreeMarker. They also support multi-language names and descriptions.
074     * </p>
075     *
076     * <p>
077     * Templates can be related to many models in Liferay, such as those for
078     * structures, dynamic data lists, and applications. This relationship can be
079     * established via the class name ID and class PK.
080     * </p>
081     *
082     * @author Brian Wing Shun Chan
083     * @author Eduardo Lundgren
084     * @author Marcellus Tavares
085     */
086    public class DDMTemplateLocalServiceImpl
087            extends DDMTemplateLocalServiceBaseImpl {
088    
089            /**
090             * Adds a template.
091             *
092             * @param  userId the primary key of the template's creator/owner
093             * @param  groupId the primary key of the group
094             * @param  classNameId the primary key of the class name for the template's
095             *         related model
096             * @param  classPK the primary key of the template's related entity
097             * @param  resourceClassNameId the primary key of the class name for
098             *         template's resource model
099             * @param  nameMap the template's locales and localized names
100             * @param  descriptionMap the template's locales and localized descriptions
101             * @param  type the template's type. For more information, see {@link
102             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
103             * @param  mode the template's mode. For more information, see {@link
104             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
105             * @param  language the template's script language. For more information,
106             *         see {@link
107             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
108             * @param  script the template's script
109             * @param  serviceContext the service context to be applied. Can set the
110             *         UUID, creation date, modification date, guest permissions, and
111             *         group permissions for the template.
112             * @return the template
113             * @throws PortalException if a portal exception occurred
114             */
115            @Override
116            public DDMTemplate addTemplate(
117                            long userId, long groupId, long classNameId, long classPK,
118                            long resourceClassNameId, Map<Locale, String> nameMap,
119                            Map<Locale, String> descriptionMap, String type, String mode,
120                            String language, String script, ServiceContext serviceContext)
121                    throws PortalException {
122    
123                    return addTemplate(
124                            userId, groupId, classNameId, classPK, resourceClassNameId, null,
125                            nameMap, descriptionMap, type, mode, language, script, false, false,
126                            null, null, serviceContext);
127            }
128    
129            /**
130             * Adds a template with additional parameters.
131             *
132             * @param  userId the primary key of the template's creator/owner
133             * @param  groupId the primary key of the group
134             * @param  classNameId the primary key of the class name for the template's
135             *         related model
136             * @param  classPK the primary key of the template's related entity
137             * @param  resourceClassNameId the primary key of the class name for
138             *         template's resource model
139             * @param  templateKey the unique string identifying the template
140             *         (optionally <code>null</code>)
141             * @param  nameMap the template's locales and localized names
142             * @param  descriptionMap the template's locales and localized descriptions
143             * @param  type the template's type. For more information, see {@link
144             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
145             * @param  mode the template's mode. For more information, see {@link
146             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
147             * @param  language the template's script language. For more information,
148             *         see {@link
149             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
150             * @param  script the template's script
151             * @param  cacheable whether the template is cacheable
152             * @param  smallImage whether the template has a small image
153             * @param  smallImageURL the template's small image URL (optionally
154             *         <code>null</code>)
155             * @param  smallImageFile the template's small image file (optionally
156             *         <code>null</code>)
157             * @param  serviceContext the service context to be applied. Can set the
158             *         UUID, creation date, modification date, guest permissions, and
159             *         group permissions for the template.
160             * @return the template
161             * @throws PortalException if a portal exception occurred
162             */
163            @Override
164            public DDMTemplate addTemplate(
165                            long userId, long groupId, long classNameId, long classPK,
166                            long resourceClassNameId, String templateKey,
167                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
168                            String type, String mode, String language, String script,
169                            boolean cacheable, boolean smallImage, String smallImageURL,
170                            File smallImageFile, ServiceContext serviceContext)
171                    throws PortalException {
172    
173                    // Template
174    
175                    User user = userPersistence.findByPrimaryKey(userId);
176    
177                    if (Validator.isNull(templateKey)) {
178                            templateKey = String.valueOf(counterLocalService.increment());
179                    }
180                    else {
181                            templateKey = StringUtil.toUpperCase(templateKey.trim());
182                    }
183    
184                    script = formatScript(type, language, script);
185    
186                    byte[] smallImageBytes = null;
187    
188                    if (smallImage) {
189                            try {
190                                    smallImageBytes = FileUtil.getBytes(smallImageFile);
191                            }
192                            catch (IOException ioe) {
193                            }
194    
195                            if ((smallImageBytes == null) || Validator.isUrl(smallImageURL)) {
196                                    smallImage = false;
197                            }
198                    }
199    
200                    validate(
201                            groupId, classNameId, templateKey, nameMap, script, smallImage,
202                            smallImageURL, smallImageFile, smallImageBytes);
203    
204                    long templateId = counterLocalService.increment();
205    
206                    DDMTemplate template = ddmTemplatePersistence.create(templateId);
207    
208                    template.setUuid(serviceContext.getUuid());
209                    template.setGroupId(groupId);
210                    template.setCompanyId(user.getCompanyId());
211                    template.setUserId(user.getUserId());
212                    template.setUserName(user.getFullName());
213                    template.setVersionUserId(user.getUserId());
214                    template.setVersionUserName(user.getFullName());
215                    template.setClassNameId(classNameId);
216                    template.setClassPK(classPK);
217                    template.setResourceClassNameId(resourceClassNameId);
218                    template.setTemplateKey(templateKey);
219                    template.setVersion(DDMTemplateConstants.VERSION_DEFAULT);
220                    template.setNameMap(nameMap);
221                    template.setDescriptionMap(descriptionMap);
222                    template.setType(type);
223                    template.setMode(mode);
224                    template.setLanguage(language);
225                    template.setScript(script);
226                    template.setCacheable(cacheable);
227                    template.setSmallImage(smallImage);
228                    template.setSmallImageId(counterLocalService.increment());
229                    template.setSmallImageURL(smallImageURL);
230    
231                    ddmTemplatePersistence.update(template);
232    
233                    // Resources
234    
235                    if (serviceContext.isAddGroupPermissions() ||
236                            serviceContext.isAddGuestPermissions()) {
237    
238                            addTemplateResources(
239                                    template, serviceContext.isAddGroupPermissions(),
240                                    serviceContext.isAddGuestPermissions());
241                    }
242                    else {
243                            addTemplateResources(
244                                    template, serviceContext.getGroupPermissions(),
245                                    serviceContext.getGuestPermissions());
246                    }
247    
248                    // Small image
249    
250                    saveImages(
251                            smallImage, template.getSmallImageId(), smallImageFile,
252                            smallImageBytes);
253    
254                    // Template version
255    
256                    addTemplateVersion(
257                            user, template, DDMTemplateConstants.VERSION_DEFAULT,
258                            serviceContext);
259    
260                    return template;
261            }
262    
263            /**
264             * Adds the resources to the template.
265             *
266             * @param  template the template to add resources to
267             * @param  addGroupPermissions whether to add group permissions
268             * @param  addGuestPermissions whether to add guest permissions
269             * @throws PortalException if a portal exception occurred
270             */
271            @Override
272            public void addTemplateResources(
273                            DDMTemplate template, boolean addGroupPermissions,
274                            boolean addGuestPermissions)
275                    throws PortalException {
276    
277                    resourceLocalService.addResources(
278                            template.getCompanyId(), template.getGroupId(),
279                            template.getUserId(), DDMTemplate.class.getName(),
280                            template.getTemplateId(), false, addGroupPermissions,
281                            addGuestPermissions);
282            }
283    
284            /**
285             * Adds the model resources with the permissions to the template.
286             *
287             * @param  template the template to add resources to
288             * @param  groupPermissions the group permissions to be added
289             * @param  guestPermissions the guest permissions to be added
290             * @throws PortalException if a portal exception occurred
291             */
292            @Override
293            public void addTemplateResources(
294                            DDMTemplate template, String[] groupPermissions,
295                            String[] guestPermissions)
296                    throws PortalException {
297    
298                    resourceLocalService.addModelResources(
299                            template.getCompanyId(), template.getGroupId(),
300                            template.getUserId(), DDMTemplate.class.getName(),
301                            template.getTemplateId(), groupPermissions, guestPermissions);
302            }
303    
304            /**
305             * Copies the template, creating a new template with all the values
306             * extracted from the original one. This method supports defining a new name
307             * and description.
308             *
309             * @param  userId the primary key of the template's creator/owner
310             * @param  templateId the primary key of the template to be copied
311             * @param  nameMap the new template's locales and localized names
312             * @param  descriptionMap the new template's locales and localized
313             *         descriptions
314             * @param  serviceContext the service context to be applied. Can set the
315             *         UUID, creation date, modification date, guest permissions, and
316             *         group permissions for the template.
317             * @return the new template
318             * @throws PortalException if a portal exception occurred
319             */
320            @Override
321            public DDMTemplate copyTemplate(
322                            long userId, long templateId, Map<Locale, String> nameMap,
323                            Map<Locale, String> descriptionMap, ServiceContext serviceContext)
324                    throws PortalException {
325    
326                    DDMTemplate template = ddmTemplatePersistence.findByPrimaryKey(
327                            templateId);
328    
329                    return copyTemplate(
330                            userId, template, template.getClassPK(), nameMap, descriptionMap,
331                            serviceContext);
332            }
333    
334            @Override
335            public DDMTemplate copyTemplate(
336                            long userId, long templateId, ServiceContext serviceContext)
337                    throws PortalException {
338    
339                    DDMTemplate template = ddmTemplatePersistence.findByPrimaryKey(
340                            templateId);
341    
342                    return copyTemplate(
343                            userId, template, template.getClassPK(), template.getNameMap(),
344                            template.getDescriptionMap(), serviceContext);
345            }
346    
347            /**
348             * Copies all the templates matching the class name ID, class PK, and type.
349             * This method creates new templates, extracting all the values from the old
350             * ones and updating their class PKs.
351             *
352             * @param  userId the primary key of the template's creator/owner
353             * @param  classNameId the primary key of the class name for the template's
354             *         related model
355             * @param  oldClassPK the primary key of the old template's related entity
356             * @param  newClassPK the primary key of the new template's related entity
357             * @param  type the template's type. For more information, see {@link
358             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
359             * @param  serviceContext the service context to be applied. Can set the
360             *         creation date, modification date, guest permissions, and group
361             *         permissions for the new templates.
362             * @return the new templates
363             * @throws PortalException if a portal exception occurred
364             */
365            @Override
366            public List<DDMTemplate> copyTemplates(
367                            long userId, long classNameId, long oldClassPK, long newClassPK,
368                            String type, ServiceContext serviceContext)
369                    throws PortalException {
370    
371                    List<DDMTemplate> newTemplates = new ArrayList<>();
372    
373                    List<DDMTemplate> oldTemplates = ddmTemplatePersistence.findByC_C_T(
374                            classNameId, oldClassPK, type);
375    
376                    for (DDMTemplate oldTemplate : oldTemplates) {
377                            DDMTemplate newTemplate = copyTemplate(
378                                    userId, oldTemplate, newClassPK, oldTemplate.getNameMap(),
379                                    oldTemplate.getDescriptionMap(), serviceContext);
380    
381                            newTemplates.add(newTemplate);
382                    }
383    
384                    return newTemplates;
385            }
386    
387            /**
388             * Deletes the template and its resources.
389             *
390             * @param  template the template to be deleted
391             * @throws PortalException if a portal exception occurred
392             */
393            @Override
394            @SystemEvent(type = SystemEventConstants.TYPE_DELETE)
395            public void deleteTemplate(DDMTemplate template) throws PortalException {
396    
397                    // Template
398    
399                    if (ddmTemplateLinkPersistence.countByTemplateId(
400                                    template.getTemplateId()) > 0) {
401    
402                            throw new RequiredTemplateException.
403                                    MustNotDeleteTemplateReferencedByTemplateLinks(
404                                            template.getTemplateId());
405                    }
406    
407                    ddmTemplatePersistence.remove(template);
408    
409                    // Resources
410    
411                    resourceLocalService.deleteResource(
412                            template.getCompanyId(), DDMTemplate.class.getName(),
413                            ResourceConstants.SCOPE_INDIVIDUAL, template.getTemplateId());
414            }
415    
416            /**
417             * Deletes the template and its resources.
418             *
419             * @param  templateId the primary key of the template to be deleted
420             * @throws PortalException if a portal exception occurred
421             */
422            @Override
423            public void deleteTemplate(long templateId) throws PortalException {
424                    DDMTemplate template = ddmTemplatePersistence.findByPrimaryKey(
425                            templateId);
426    
427                    ddmTemplateLocalService.deleteTemplate(template);
428            }
429    
430            /**
431             * Deletes all the templates of the group.
432             *
433             * @param  groupId the primary key of the group
434             * @throws PortalException if a portal exception occurred
435             */
436            @Override
437            public void deleteTemplates(long groupId) throws PortalException {
438                    List<DDMTemplate> templates = ddmTemplatePersistence.findByGroupId(
439                            groupId);
440    
441                    for (DDMTemplate template : templates) {
442                            ddmTemplateLocalService.deleteTemplate(template);
443                    }
444            }
445    
446            @Override
447            public void deleteTemplates(long groupId, long classNameId)
448                    throws PortalException {
449    
450                    List<DDMTemplate> templates = ddmTemplatePersistence.findByG_C(
451                            groupId, classNameId);
452    
453                    for (DDMTemplate template : templates) {
454                            ddmTemplateLocalService.deleteTemplate(template);
455                    }
456            }
457    
458            /**
459             * Returns the template matching the group and template key.
460             *
461             * @param  groupId the primary key of the group
462             * @param  classNameId the primary key of the class name for the template's
463             *         related model
464             * @param  templateKey the unique string identifying the template
465             * @return the matching template, or <code>null</code> if a matching
466             *         template could not be found
467             */
468            @Override
469            public DDMTemplate fetchTemplate(
470                    long groupId, long classNameId, String templateKey) {
471    
472                    templateKey = StringUtil.toUpperCase(templateKey.trim());
473    
474                    return ddmTemplatePersistence.fetchByG_C_T(
475                            groupId, classNameId, templateKey);
476            }
477    
478            /**
479             * Returns the template matching the group and template key, optionally
480             * searching ancestor sites (that have sharing enabled) and global scoped
481             * sites.
482             *
483             * <p>
484             * This method first searches in the given group. If the template is still
485             * not found and <code>includeAncestorTemplates</code> is set to
486             * <code>true</code>, this method searches the group's ancestor sites (that
487             * have sharing enabled) and lastly searches global scoped sites.
488             * </p>
489             *
490             * @param  groupId the primary key of the group
491             * @param  classNameId the primary key of the class name for the template's
492             *         related model
493             * @param  templateKey the unique string identifying the template
494             * @param  includeAncestorTemplates whether to include ancestor sites (that
495             *         have sharing enabled) and include global scoped sites in the
496             *         search in the search
497             * @return the matching template, or <code>null</code> if a matching
498             *         template could not be found
499             * @throws PortalException if a portal exception occurred
500             */
501            @Override
502            public DDMTemplate fetchTemplate(
503                            long groupId, long classNameId, String templateKey,
504                            boolean includeAncestorTemplates)
505                    throws PortalException {
506    
507                    templateKey = StringUtil.toUpperCase(templateKey.trim());
508    
509                    DDMTemplate template = ddmTemplatePersistence.fetchByG_C_T(
510                            groupId, classNameId, templateKey);
511    
512                    if (template != null) {
513                            return template;
514                    }
515    
516                    if (!includeAncestorTemplates) {
517                            return null;
518                    }
519    
520                    for (long ancestorSiteGroupId :
521                                    PortalUtil.getAncestorSiteGroupIds(groupId)) {
522    
523                            template = ddmTemplatePersistence.fetchByG_C_T(
524                                    ancestorSiteGroupId, classNameId, templateKey);
525    
526                            if (template != null) {
527                                    return template;
528                            }
529                    }
530    
531                    return null;
532            }
533    
534            /**
535             * Returns the template with the ID.
536             *
537             * @param  templateId the primary key of the template
538             * @return the template with the ID
539             * @throws PortalException if a matching template could not be found
540             */
541            @Override
542            public DDMTemplate getTemplate(long templateId) throws PortalException {
543                    return ddmTemplatePersistence.findByPrimaryKey(templateId);
544            }
545    
546            /**
547             * Returns the template matching the group and template key.
548             *
549             * @param  groupId the primary key of the group
550             * @param  classNameId the primary key of the class name for the template's
551             *         related model
552             * @param  templateKey the unique string identifying the template
553             * @return the matching template
554             * @throws PortalException if a matching template could not be found
555             */
556            @Override
557            public DDMTemplate getTemplate(
558                            long groupId, long classNameId, String templateKey)
559                    throws PortalException {
560    
561                    templateKey = StringUtil.toUpperCase(templateKey.trim());
562    
563                    return ddmTemplatePersistence.findByG_C_T(
564                            groupId, classNameId, templateKey);
565            }
566    
567            /**
568             * Returns the template matching the group and template key, optionally
569             * searching ancestor sites (that have sharing enabled) and global scoped
570             * sites.
571             *
572             * <p>
573             * This method first searches in the group. If the template is still not
574             * found and <code>includeAncestorTemplates</code> is set to
575             * <code>true</code>, this method searches the group's ancestor sites (that
576             * have sharing enabled) and lastly searches global scoped sites.
577             * </p>
578             *
579             * @param  groupId the primary key of the group
580             * @param  classNameId the primary key of the class name for the template's
581             *         related model
582             * @param  templateKey the unique string identifying the template
583             * @param  includeAncestorTemplates whether to include ancestor sites (that
584             *         have sharing enabled) and include global scoped sites in the
585             *         search in the search
586             * @return the matching template
587             * @throws PortalException if a matching template could not be found
588             */
589            @Override
590            public DDMTemplate getTemplate(
591                            long groupId, long classNameId, String templateKey,
592                            boolean includeAncestorTemplates)
593                    throws PortalException {
594    
595                    templateKey = StringUtil.toUpperCase(templateKey.trim());
596    
597                    DDMTemplate template = ddmTemplatePersistence.fetchByG_C_T(
598                            groupId, classNameId, templateKey);
599    
600                    if (template != null) {
601                            return template;
602                    }
603    
604                    if (!includeAncestorTemplates) {
605                            throw new NoSuchTemplateException(
606                                    "No DDMTemplate exists with the template key " + templateKey);
607                    }
608    
609                    for (long ancestorSiteGroupId :
610                                    PortalUtil.getAncestorSiteGroupIds(groupId)) {
611    
612                            template = ddmTemplatePersistence.fetchByG_C_T(
613                                    ancestorSiteGroupId, classNameId, templateKey);
614    
615                            if (template != null) {
616                                    return template;
617                            }
618                    }
619    
620                    throw new NoSuchTemplateException(
621                            "No DDMTemplate exists with the template key " + templateKey +
622                                    " in the ancestor groups");
623            }
624    
625            @Override
626            public DDMTemplate getTemplateBySmallImageId(long smallImageId)
627                    throws PortalException {
628    
629                    return ddmTemplatePersistence.findBySmallImageId(smallImageId);
630            }
631    
632            /**
633             * Returns all the templates with the class PK.
634             *
635             * @param  classPK the primary key of the template's related entity
636             * @return the templates with the class PK
637             */
638            @Override
639            public List<DDMTemplate> getTemplates(long classPK) {
640                    return ddmTemplatePersistence.findByClassPK(classPK);
641            }
642    
643            /**
644             * Returns all the templates matching the group and class name ID.
645             *
646             * @param  groupId the primary key of the group
647             * @param  classNameId the primary key of the class name for the template's
648             *         related model
649             * @return the matching templates
650             */
651            @Override
652            public List<DDMTemplate> getTemplates(long groupId, long classNameId) {
653                    return ddmTemplatePersistence.findByG_C(groupId, classNameId);
654            }
655    
656            /**
657             * Returns all the templates matching the group, class name ID, and class
658             * PK.
659             *
660             * @param  groupId the primary key of the group
661             * @param  classNameId the primary key of the class name for the template's
662             *         related model
663             * @param  classPK the primary key of the template's related entity
664             * @return the matching templates
665             */
666            @Override
667            public List<DDMTemplate> getTemplates(
668                    long groupId, long classNameId, long classPK) {
669    
670                    return ddmTemplatePersistence.findByG_C_C(
671                            groupId, classNameId, classPK);
672            }
673    
674            @Override
675            public List<DDMTemplate> getTemplates(
676                            long groupId, long classNameId, long classPK,
677                            boolean includeAncestorTemplates)
678                    throws PortalException {
679    
680                    List<DDMTemplate> ddmTemplates = new ArrayList<>();
681    
682                    ddmTemplates.addAll(
683                            ddmTemplatePersistence.findByG_C_C(groupId, classNameId, classPK));
684    
685                    if (!includeAncestorTemplates) {
686                            return ddmTemplates;
687                    }
688    
689                    ddmTemplates.addAll(
690                            ddmTemplatePersistence.findByG_C_C(
691                                    PortalUtil.getAncestorSiteGroupIds(groupId), classNameId,
692                                    classPK));
693    
694                    return ddmTemplates;
695            }
696    
697            /**
698             * Returns all the templates matching the group, class name ID, class PK,
699             * and type.
700             *
701             * @param  groupId the primary key of the group
702             * @param  classNameId the primary key of the class name for the template's
703             *         related model
704             * @param  classPK the primary key of the template's related entity
705             * @param  type the template's type. For more information, see {@link
706             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
707             * @return the matching templates
708             */
709            @Override
710            public List<DDMTemplate> getTemplates(
711                    long groupId, long classNameId, long classPK, String type) {
712    
713                    return ddmTemplatePersistence.findByG_C_C_T(
714                            groupId, classNameId, classPK, type);
715            }
716    
717            /**
718             * Returns all the templates matching the group, class name ID, class PK,
719             * type, and mode.
720             *
721             * @param  groupId the primary key of the group
722             * @param  classNameId the primary key of the class name for the template's
723             *         related model
724             * @param  classPK the primary key of the template's related entity
725             * @param  type the template's type. For more information, see {@link
726             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
727             * @param  mode the template's mode. For more information, see {@link
728             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
729             * @return the matching templates
730             */
731            @Override
732            public List<DDMTemplate> getTemplates(
733                    long groupId, long classNameId, long classPK, String type,
734                    String mode) {
735    
736                    return ddmTemplatePersistence.findByG_C_C_T_M(
737                            groupId, classNameId, classPK, type, mode);
738            }
739    
740            @Override
741            public List<DDMTemplate> getTemplates(
742                    long[] groupIds, long classNameId, long classPK) {
743    
744                    return ddmTemplatePersistence.findByG_C_C(
745                            groupIds, classNameId, classPK);
746            }
747    
748            @Override
749            public List<DDMTemplate> getTemplatesByClassPK(long groupId, long classPK) {
750                    return ddmTemplatePersistence.findByG_CPK(groupId, classPK);
751            }
752    
753            @Override
754            public List<DDMTemplate> getTemplatesByClassPK(
755                    long groupId, long classPK, int start, int end) {
756    
757                    return ddmTemplatePersistence.findByG_CPK(groupId, classPK, start, end);
758            }
759    
760            @Override
761            public List<DDMTemplate> getTemplatesByClassPK(
762                    long[] groupIds, long classPK) {
763    
764                    return ddmTemplatePersistence.findByG_CPK(groupIds, classPK);
765            }
766    
767            /**
768             * Returns the number of templates matching the group and class PK.
769             *
770             * @param  groupId the primary key of the group
771             * @param  classPK the primary key of the template's related entity
772             * @return the number of templates belonging to the group and class PK
773             */
774            @Override
775            public int getTemplatesByClassPKCount(long groupId, long classPK) {
776                    return ddmTemplatePersistence.countByG_CPK(groupId, classPK);
777            }
778    
779            /**
780             * Returns an ordered range of all the templates matching the group and
781             * structure class name ID.
782             *
783             * <p>
784             * Useful when paginating results. Returns a maximum of <code>end -
785             * start</code> instances. <code>start</code> and <code>end</code> are not
786             * primary keys, they are indexes in the result set. Thus, <code>0</code>
787             * refers to the first result in the set. Setting both <code>start</code>
788             * and <code>end</code> to {@link
789             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
790             * result set.
791             * </p>
792             *
793             * @param  groupId the primary key of the group
794             * @param  structureClassNameId the primary key of the class name for the
795             *         template's related structure
796             * @param  start the lower bound of the range of templates to return
797             * @param  end the upper bound of the range of templates to return (not
798             *         inclusive)
799             * @param  orderByComparator the comparator to order the templates
800             *         (optionally <code>null</code>)
801             * @return the range of matching templates ordered by the comparator
802             */
803            @Override
804            public List<DDMTemplate> getTemplatesByStructureClassNameId(
805                    long groupId, long structureClassNameId, int start, int end,
806                    OrderByComparator<DDMTemplate> orderByComparator) {
807    
808                    return ddmTemplateFinder.findByG_SC(
809                            groupId, structureClassNameId, start, end, orderByComparator);
810            }
811    
812            /**
813             * Returns the number of templates matching the group and structure class
814             * name ID, including Generic Templates.
815             *
816             * @param  groupId the primary key of the group
817             * @param  structureClassNameId the primary key of the class name for the
818             *         template's related structure
819             * @return the number of matching templates
820             */
821            @Override
822            public int getTemplatesByStructureClassNameIdCount(
823                    long groupId, long structureClassNameId) {
824    
825                    return ddmTemplateFinder.countByG_SC(groupId, structureClassNameId);
826            }
827    
828            /**
829             * Returns the number of templates belonging to the group.
830             *
831             * @param  groupId the primary key of the group
832             * @return the number of templates belonging to the group
833             */
834            @Override
835            public int getTemplatesCount(long groupId) {
836                    return ddmTemplatePersistence.countByGroupId(groupId);
837            }
838    
839            /**
840             * Returns the number of templates matching the group and class name ID.
841             *
842             * @param  groupId the primary key of the group
843             * @param  classNameId the primary key of the class name for the template's
844             *         related model
845             * @return the number of matching templates
846             */
847            @Override
848            public int getTemplatesCount(long groupId, long classNameId) {
849                    return ddmTemplatePersistence.countByG_C(groupId, classNameId);
850            }
851    
852            /**
853             * Returns the number of templates matching the group, class name ID, and
854             * class PK.
855             *
856             * @param  groupId the primary key of the group
857             * @param  classNameId the primary key of the class name for the template's
858             *         related model
859             * @param  classPK the primary key of the template's related entity
860             * @return the number of matching templates
861             */
862            @Override
863            public int getTemplatesCount(long groupId, long classNameId, long classPK) {
864                    return ddmTemplatePersistence.countByG_C_C(
865                            groupId, classNameId, classPK);
866            }
867    
868            @Override
869            public void revertTemplate(
870                            long userId, long templateId, String version,
871                            ServiceContext serviceContext)
872                    throws PortalException {
873    
874                    DDMTemplateVersion templateVersion =
875                            ddmTemplateVersionLocalService.getTemplateVersion(
876                                    templateId, version);
877    
878                    if (!templateVersion.isApproved()) {
879                            throw new InvalidTemplateVersionException(
880                                    "Unable to revert from an unapproved template version");
881                    }
882    
883                    DDMTemplate template = templateVersion.getTemplate();
884    
885                    serviceContext.setAttribute("majorVersion", Boolean.TRUE);
886                    serviceContext.setAttribute(
887                            "status", WorkflowConstants.STATUS_APPROVED);
888                    serviceContext.setCommand(Constants.REVERT);
889    
890                    ddmTemplateLocalService.updateTemplate(
891                            userId, templateId, templateVersion.getClassPK(),
892                            templateVersion.getNameMap(), templateVersion.getDescriptionMap(),
893                            template.getType(), template.getMode(),
894                            templateVersion.getLanguage(), templateVersion.getScript(),
895                            template.getCacheable(), serviceContext);
896            }
897    
898            /**
899             * Returns an ordered range of all the templates matching the group, class
900             * name ID, class PK, type, and mode, and matching the keywords in the
901             * template names and descriptions.
902             *
903             * <p>
904             * Useful when paginating results. Returns a maximum of <code>end -
905             * start</code> instances. <code>start</code> and <code>end</code> are not
906             * primary keys, they are indexes in the result set. Thus, <code>0</code>
907             * refers to the first result in the set. Setting both <code>start</code>
908             * and <code>end</code> to {@link
909             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
910             * result set.
911             * </p>
912             *
913             * @param  companyId the primary key of the template's company
914             * @param  groupId the primary key of the group
915             * @param  classNameId the primary key of the class name for the template's
916             *         related model
917             * @param  classPK the primary key of the template's related entity
918             * @param  resourceClassNameId the primary key of the class name for
919             *         template's resource model
920             * @param  keywords the keywords (space separated), which may occur in the
921             *         template's name or description (optionally <code>null</code>)
922             * @param  type the template's type (optionally <code>null</code>). For more
923             *         information, see {@link
924             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
925             * @param  mode the template's mode (optionally <code>null</code>). For more
926             *         information, see {@link
927             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
928             * @param  start the lower bound of the range of templates to return
929             * @param  end the upper bound of the range of templates to return (not
930             *         inclusive)
931             * @param  orderByComparator the comparator to order the templates
932             *         (optionally <code>null</code>)
933             * @return the range of matching templates ordered by the comparator
934             */
935            @Override
936            public List<DDMTemplate> search(
937                    long companyId, long groupId, long classNameId, long classPK,
938                    long resourceClassNameId, String keywords, String type, String mode,
939                    int start, int end, OrderByComparator<DDMTemplate> orderByComparator) {
940    
941                    return ddmTemplateFinder.findByKeywords(
942                            companyId, groupId, classNameId, classPK, resourceClassNameId,
943                            keywords, type, mode, start, end, orderByComparator);
944            }
945    
946            /**
947             * Returns an ordered range of all the templates matching the group, class
948             * name ID, class PK, name keyword, description keyword, type, mode, and
949             * language.
950             *
951             * <p>
952             * Useful when paginating results. Returns a maximum of <code>end -
953             * start</code> instances. <code>start</code> and <code>end</code> are not
954             * primary keys, they are indexes in the result set. Thus, <code>0</code>
955             * refers to the first result in the set. Setting both <code>start</code>
956             * and <code>end</code> to {@link
957             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
958             * result set.
959             * </p>
960             *
961             * @param  companyId the primary key of the template's company
962             * @param  groupId the primary key of the group
963             * @param  classNameId the primary key of the class name for the template's
964             *         related model
965             * @param  classPK the primary key of the template's related entity
966             * @param  resourceClassNameId the primary key of the class name for
967             *         template's resource model
968             * @param  name the name keywords (optionally <code>null</code>)
969             * @param  description the description keywords (optionally
970             *         <code>null</code>)
971             * @param  type the template's type (optionally <code>null</code>). For more
972             *         information, see {@link
973             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
974             * @param  mode the template's mode (optionally <code>null</code>). For more
975             *         information, see {@link
976             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
977             * @param  language the template's script language (optionally
978             *         <code>null</code>). For more information, see {@link
979             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
980             * @param  andOperator whether every field must match its keywords, or just
981             *         one field
982             * @param  start the lower bound of the range of templates to return
983             * @param  end the upper bound of the range of templates to return (not
984             *         inclusive)
985             * @param  orderByComparator the comparator to order the templates
986             *         (optionally <code>null</code>)
987             * @return the range of matching templates ordered by the comparator
988             */
989            @Override
990            public List<DDMTemplate> search(
991                    long companyId, long groupId, long classNameId, long classPK,
992                    long resourceClassNameId, String name, String description, String type,
993                    String mode, String language, boolean andOperator, int start, int end,
994                    OrderByComparator<DDMTemplate> orderByComparator) {
995    
996                    return ddmTemplateFinder.findByC_G_C_C_R_N_D_T_M_L(
997                            companyId, groupId, classNameId, classPK, resourceClassNameId, name,
998                            description, type, mode, language, andOperator, start, end,
999                            orderByComparator);
1000            }
1001    
1002            /**
1003             * Returns an ordered range of all the templates matching the group IDs,
1004             * class Name IDs, class PK, type, and mode, and include the keywords on its
1005             * names and descriptions.
1006             *
1007             * <p>
1008             * Useful when paginating results. Returns a maximum of <code>end -
1009             * start</code> instances. <code>start</code> and <code>end</code> are not
1010             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1011             * refers to the first result in the set. Setting both <code>start</code>
1012             * and <code>end</code> to {@link
1013             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1014             * result set.
1015             * </p>
1016             *
1017             * @param  companyId the primary key of the template's company
1018             * @param  groupIds the primary keys of the groups
1019             * @param  classNameIds the primary keys of the entity's instances the
1020             *         templates are related to
1021             * @param  classPKs the primary keys of the template's related entities
1022             * @param  resourceClassNameId the primary key of the class name for
1023             *         template's resource model
1024             * @param  keywords the keywords (space separated), which may occur in the
1025             *         template's name or description (optionally <code>null</code>)
1026             * @param  type the template's type (optionally <code>null</code>). For more
1027             *         information, see {@link
1028             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1029             * @param  mode the template's mode (optionally <code>null</code>). For more
1030             *         information, see {@link
1031             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1032             * @param  start the lower bound of the range of templates to return
1033             * @param  end the upper bound of the range of templates to return (not
1034             *         inclusive)
1035             * @param  orderByComparator the comparator to order the templates
1036             *         (optionally <code>null</code>)
1037             * @return the range of matching templates ordered by the comparator
1038             */
1039            @Override
1040            public List<DDMTemplate> search(
1041                    long companyId, long[] groupIds, long[] classNameIds, long[] classPKs,
1042                    long resourceClassNameId, String keywords, String type, String mode,
1043                    int start, int end, OrderByComparator<DDMTemplate> orderByComparator) {
1044    
1045                    return ddmTemplateFinder.findByKeywords(
1046                            companyId, groupIds, classNameIds, classPKs, resourceClassNameId,
1047                            keywords, type, mode, start, end, orderByComparator);
1048            }
1049    
1050            /**
1051             * Returns an ordered range of all the templates matching the group IDs,
1052             * class name IDs, class PK, name keyword, description keyword, type, mode,
1053             * and language.
1054             *
1055             * <p>
1056             * Useful when paginating results. Returns a maximum of <code>end -
1057             * start</code> instances. <code>start</code> and <code>end</code> are not
1058             * primary keys, they are indexes in the result set. Thus, <code>0</code>
1059             * refers to the first result in the set. Setting both <code>start</code>
1060             * and <code>end</code> to {@link
1061             * com.liferay.portal.kernel.dao.orm.QueryUtil#ALL_POS} will return the full
1062             * result set.
1063             * </p>
1064             *
1065             * @param  companyId the primary key of the template's company
1066             * @param  groupIds the primary keys of the groups
1067             * @param  classNameIds the primary keys of the entity's instances the
1068             *         templates are related to
1069             * @param  classPKs the primary keys of the template's related entities
1070             * @param  resourceClassNameId the primary key of the class name for
1071             *         template's resource model
1072             * @param  name the name keywords (optionally <code>null</code>)
1073             * @param  description the description keywords (optionally
1074             *         <code>null</code>)
1075             * @param  type the template's type (optionally <code>null</code>). For more
1076             *         information, see {@link
1077             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1078             * @param  mode the template's mode (optionally <code>null</code>). For more
1079             *         information, see {@link
1080             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1081             * @param  language the template's script language (optionally
1082             *         <code>null</code>). For more information, see {@link
1083             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1084             * @param  andOperator whether every field must match its keywords, or just
1085             *         one field.
1086             * @param  start the lower bound of the range of templates to return
1087             * @param  end the upper bound of the range of templates to return (not
1088             *         inclusive)
1089             * @param  orderByComparator the comparator to order the templates
1090             *         (optionally <code>null</code>)
1091             * @return the range of matching templates ordered by the comparator
1092             */
1093            @Override
1094            public List<DDMTemplate> search(
1095                    long companyId, long[] groupIds, long[] classNameIds, long[] classPKs,
1096                    long resourceClassNameId, String name, String description, String type,
1097                    String mode, String language, boolean andOperator, int start, int end,
1098                    OrderByComparator<DDMTemplate> orderByComparator) {
1099    
1100                    return ddmTemplateFinder.findByC_G_C_C_R_N_D_T_M_L(
1101                            companyId, groupIds, classNameIds, classPKs, resourceClassNameId,
1102                            name, description, type, mode, language, andOperator, start, end,
1103                            orderByComparator);
1104            }
1105    
1106            /**
1107             * Returns the number of templates matching the group, class name ID, class
1108             * PK, type, and matching the keywords in the template names and
1109             * descriptions.
1110             *
1111             * @param  companyId the primary key of the template's company
1112             * @param  groupId the primary key of the group
1113             * @param  classNameId the primary key of the class name for the template's
1114             *         related model
1115             * @param  classPK the primary key of the template's related entity
1116             * @param  resourceClassNameId the primary key of the class name for
1117             *         template's resource model
1118             * @param  keywords the keywords (space separated), which may occur in the
1119             *         template's name or description (optionally <code>null</code>)
1120             * @param  type the template's type (optionally <code>null</code>). For more
1121             *         information, see {@link
1122             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1123             * @param  mode the template's mode (optionally <code>null</code>). For more
1124             *         information, see {@link
1125             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1126             * @return the number of matching templates
1127             */
1128            @Override
1129            public int searchCount(
1130                    long companyId, long groupId, long classNameId, long classPK,
1131                    long resourceClassNameId, String keywords, String type, String mode) {
1132    
1133                    return ddmTemplateFinder.countByKeywords(
1134                            companyId, groupId, classNameId, classPK, resourceClassNameId,
1135                            keywords, type, mode);
1136            }
1137    
1138            /**
1139             * Returns the number of templates matching the group, class name ID, class
1140             * PK, name keyword, description keyword, type, mode, and language.
1141             *
1142             * @param  companyId the primary key of the template's company
1143             * @param  groupId the primary key of the group
1144             * @param  classNameId the primary key of the class name for the template's
1145             *         related model
1146             * @param  classPK the primary key of the template's related entity
1147             * @param  resourceClassNameId the primary key of the class name for
1148             *         template's resource model
1149             * @param  name the name keywords (optionally <code>null</code>)
1150             * @param  description the description keywords (optionally
1151             *         <code>null</code>)
1152             * @param  type the template's type (optionally <code>null</code>). For more
1153             *         information, see {@link
1154             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1155             * @param  mode the template's mode (optionally <code>null</code>). For more
1156             *         information, see {@link
1157             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1158             * @param  language the template's script language (optionally
1159             *         <code>null</code>). For more information, see {@link
1160             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1161             * @param  andOperator whether every field must match its keywords, or just
1162             *         one field.
1163             * @return the number of matching templates
1164             */
1165            @Override
1166            public int searchCount(
1167                    long companyId, long groupId, long classNameId, long classPK,
1168                    long resourceClassNameId, String name, String description, String type,
1169                    String mode, String language, boolean andOperator) {
1170    
1171                    return ddmTemplateFinder.countByC_G_C_C_R_N_D_T_M_L(
1172                            companyId, groupId, classNameId, classPK, resourceClassNameId, name,
1173                            description, type, mode, language, andOperator);
1174            }
1175    
1176            /**
1177             * Returns the number of templates matching the group IDs, class name IDs,
1178             * class PK, type, and mode, and matching the keywords in the template names
1179             * and descriptions.
1180             *
1181             * @param  companyId the primary key of the template's company
1182             * @param  groupIds the primary keys of the groups
1183             * @param  classNameIds the primary keys of the entity's instance the
1184             *         templates are related to
1185             * @param  classPKs the primary keys of the template's related entities
1186             * @param  resourceClassNameId the primary key of the class name for
1187             *         template's resource model
1188             * @param  keywords the keywords (space separated), which may occur in the
1189             *         template's name or description (optionally <code>null</code>)
1190             * @param  type the template's type (optionally <code>null</code>). For more
1191             *         information, see {@link
1192             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1193             * @param  mode the template's mode (optionally <code>null</code>). For more
1194             *         information, see {@link
1195             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1196             * @return the number of matching templates
1197             */
1198            @Override
1199            public int searchCount(
1200                    long companyId, long[] groupIds, long[] classNameIds, long[] classPKs,
1201                    long resourceClassNameId, String keywords, String type, String mode) {
1202    
1203                    return ddmTemplateFinder.countByKeywords(
1204                            companyId, groupIds, classNameIds, classPKs, resourceClassNameId,
1205                            keywords, type, mode);
1206            }
1207    
1208            /**
1209             * Returns the number of templates matching the group IDs, class name IDs,
1210             * class PKs, name keyword, description keyword, type, mode, and language.
1211             *
1212             * @param  companyId the primary key of the templates company
1213             * @param  groupIds the primary keys of the groups
1214             * @param  classNameIds the primary keys of the entity's instance the
1215             *         templates are related to
1216             * @param  classPKs the primary keys of the template's related entities
1217             * @param  resourceClassNameId the primary key of the class name for
1218             *         template's resource model
1219             * @param  name the name keywords (optionally <code>null</code>)
1220             * @param  description the description keywords (optionally
1221             *         <code>null</code>)
1222             * @param  type the template's type (optionally <code>null</code>). For more
1223             *         information, see {@link
1224             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1225             * @param  mode the template's mode (optionally <code>null</code>). For more
1226             *         information, see {@link
1227             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1228             * @param  language the template's script language (optionally
1229             *         <code>null</code>). For more information, see {@link
1230             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1231             * @param  andOperator whether every field must match its keywords, or just
1232             *         one field.
1233             * @return the number of matching templates
1234             */
1235            @Override
1236            public int searchCount(
1237                    long companyId, long[] groupIds, long[] classNameIds, long[] classPKs,
1238                    long resourceClassNameId, String name, String description, String type,
1239                    String mode, String language, boolean andOperator) {
1240    
1241                    return ddmTemplateFinder.countByC_G_C_C_R_N_D_T_M_L(
1242                            companyId, groupIds, classNameIds, classPKs, resourceClassNameId,
1243                            name, description, type, mode, language, andOperator);
1244            }
1245    
1246            /**
1247             * Updates the template matching the ID.
1248             *
1249             * @param  userId the primary key of the template's creator/owner
1250             * @param  templateId the primary key of the template
1251             * @param  classPK the primary key of the template's related entity
1252             * @param  nameMap the template's new locales and localized names
1253             * @param  descriptionMap the template's new locales and localized
1254             *         description
1255             * @param  type the template's type. For more information, see {@link
1256             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1257             * @param  mode the template's mode. For more information, see {@link
1258             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1259             * @param  language the template's script language. For more information,
1260             *         see {@link
1261             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1262             * @param  script the template's script
1263             * @param  cacheable whether the template is cacheable
1264             * @param  smallImage whether the template has a small image
1265             * @param  smallImageURL the template's small image URL (optionally
1266             *         <code>null</code>)
1267             * @param  smallImageFile the template's small image file (optionally
1268             *         <code>null</code>)
1269             * @param  serviceContext the service context to be applied. Can set the
1270             *         modification date.
1271             * @return the updated template
1272             * @throws PortalException if a portal exception occurred
1273             */
1274            @Override
1275            public DDMTemplate updateTemplate(
1276                            long userId, long templateId, long classPK, Map<Locale,
1277                            String> nameMap, Map<Locale, String> descriptionMap, String type,
1278                            String mode, String language, String script, boolean cacheable,
1279                            boolean smallImage, String smallImageURL, File smallImageFile,
1280                            ServiceContext serviceContext)
1281                    throws PortalException {
1282    
1283                    User user = userPersistence.findByPrimaryKey(userId);
1284    
1285                    script = formatScript(type, language, script);
1286    
1287                    byte[] smallImageBytes = null;
1288    
1289                    try {
1290                            smallImageBytes = FileUtil.getBytes(smallImageFile);
1291                    }
1292                    catch (IOException ioe) {
1293                    }
1294    
1295                    validate(
1296                            nameMap, script, smallImage, smallImageURL, smallImageFile,
1297                            smallImageBytes);
1298    
1299                    DDMTemplate template = ddmTemplateLocalService.getDDMTemplate(
1300                            templateId);
1301    
1302                    if ((template.getClassPK() == 0) && (classPK > 0)) {
1303    
1304                            // Allow users to set the structure if and only if it currently does
1305                            // not have one. Otherwise, you can have bad data because there may
1306                            // be an existing content that has chosen to use a structure and
1307                            // template combination that no longer exists.
1308    
1309                            template.setClassPK(classPK);
1310                    }
1311    
1312                    DDMTemplateVersion latestTemplateVersion =
1313                            ddmTemplateVersionLocalService.getLatestTemplateVersion(templateId);
1314    
1315                    boolean majorVersion = GetterUtil.getBoolean(
1316                            serviceContext.getAttribute("majorVersion"));
1317    
1318                    String version = getNextVersion(
1319                            latestTemplateVersion.getVersion(), majorVersion);
1320    
1321                    template.setVersion(version);
1322                    template.setVersionUserId(user.getUserId());
1323                    template.setVersionUserName(user.getFullName());
1324                    template.setNameMap(nameMap);
1325                    template.setDescriptionMap(descriptionMap);
1326                    template.setType(type);
1327                    template.setMode(mode);
1328                    template.setLanguage(language);
1329                    template.setScript(script);
1330                    template.setCacheable(cacheable);
1331                    template.setSmallImage(smallImage);
1332                    template.setSmallImageURL(smallImageURL);
1333    
1334                    ddmTemplatePersistence.update(template);
1335    
1336                    // Small image
1337    
1338                    saveImages(
1339                            smallImage, template.getSmallImageId(), smallImageFile,
1340                            smallImageBytes);
1341    
1342                    // Template version
1343    
1344                    addTemplateVersion(user, template, version, serviceContext);
1345    
1346                    return template;
1347            }
1348    
1349            /**
1350             * Updates the template matching the ID.
1351             *
1352             * @param  userId the primary key of the template's creator/owner
1353             * @param  templateId the primary key of the template
1354             * @param  classPK the primary key of the template's related entity
1355             * @param  nameMap the template's new locales and localized names
1356             * @param  descriptionMap the template's new locales and localized
1357             *         description
1358             * @param  type the template's type. For more information, see {@link
1359             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1360             * @param  mode the template's mode. For more information, see {@link
1361             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1362             * @param  language the template's script language. For more information,
1363             *         see {@link
1364             *         com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants}.
1365             * @param  script the template's script
1366             * @param  cacheable whether the template is cacheable
1367             * @param  serviceContext the service context to be applied. Can set the
1368             *         modification date.
1369             * @return the updated template
1370             * @throws PortalException if a portal exception occurred
1371             */
1372            @Override
1373            public DDMTemplate updateTemplate(
1374                            long userId, long templateId, long classPK,
1375                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
1376                            String type, String mode, String language, String script,
1377                            boolean cacheable, ServiceContext serviceContext)
1378                    throws PortalException {
1379    
1380                    DDMTemplate template = ddmTemplateLocalService.getDDMTemplate(
1381                            templateId);
1382    
1383                    File smallImageFile = getSmallImageFile(template);
1384    
1385                    return updateTemplate(
1386                            userId, templateId, classPK, nameMap, descriptionMap, type, mode,
1387                            language, script, cacheable, template.isSmallImage(),
1388                            template.getSmallImageURL(), smallImageFile, serviceContext);
1389            }
1390    
1391            protected DDMTemplateVersion addTemplateVersion(
1392                    User user, DDMTemplate template, String version,
1393                    ServiceContext serviceContext) {
1394    
1395                    long templateVersionId = counterLocalService.increment();
1396    
1397                    DDMTemplateVersion templateVersion =
1398                            ddmTemplateVersionPersistence.create(templateVersionId);
1399    
1400                    templateVersion.setGroupId(template.getGroupId());
1401                    templateVersion.setCompanyId(template.getCompanyId());
1402                    templateVersion.setUserId(template.getUserId());
1403                    templateVersion.setUserName(template.getUserName());
1404                    templateVersion.setCreateDate(template.getModifiedDate());
1405                    templateVersion.setClassNameId(template.getClassNameId());
1406                    templateVersion.setClassPK(template.getClassPK());
1407                    templateVersion.setTemplateId(template.getTemplateId());
1408                    templateVersion.setVersion(version);
1409                    templateVersion.setName(template.getName());
1410                    templateVersion.setDescription(template.getDescription());
1411                    templateVersion.setLanguage(template.getLanguage());
1412                    templateVersion.setScript(template.getScript());
1413    
1414                    int status = GetterUtil.getInteger(
1415                            serviceContext.getAttribute("status"),
1416                            WorkflowConstants.STATUS_DRAFT);
1417    
1418                    templateVersion.setStatus(status);
1419    
1420                    templateVersion.setStatusByUserId(user.getUserId());
1421                    templateVersion.setStatusByUserName(user.getFullName());
1422                    templateVersion.setStatusDate(template.getModifiedDate());
1423    
1424                    ddmTemplateVersionPersistence.update(templateVersion);
1425    
1426                    return templateVersion;
1427            }
1428    
1429            protected DDMTemplate copyTemplate(
1430                            long userId, DDMTemplate template, long classPK,
1431                            Map<Locale, String> nameMap, Map<Locale, String> descriptionMap,
1432                            ServiceContext serviceContext)
1433                    throws PortalException {
1434    
1435                    File smallImageFile = getSmallImageFile(template);
1436    
1437                    return addTemplate(
1438                            userId, template.getGroupId(), template.getClassNameId(), classPK,
1439                            template.getResourceClassNameId(), null, nameMap, descriptionMap,
1440                            template.getType(), template.getMode(), template.getLanguage(),
1441                            template.getScript(), template.isCacheable(),
1442                            template.isSmallImage(), template.getSmallImageURL(),
1443                            smallImageFile, serviceContext);
1444            }
1445    
1446            protected String formatScript(String type, String language, String script)
1447                    throws PortalException {
1448    
1449                    if (language.equals(TemplateConstants.LANG_TYPE_XSL)) {
1450                            try {
1451                                    script = DDMXMLUtil.validateXML(script);
1452                            }
1453                            catch (PortalException pe) {
1454                                    throw new TemplateScriptException(pe);
1455                            }
1456    
1457                            script = DDMXMLUtil.formatXML(script);
1458                    }
1459    
1460                    return script;
1461            }
1462    
1463            protected String getNextVersion(String version, boolean majorVersion) {
1464                    int[] versionParts = StringUtil.split(version, StringPool.PERIOD, 0);
1465    
1466                    if (majorVersion) {
1467                            versionParts[0]++;
1468                            versionParts[1] = 0;
1469                    }
1470                    else {
1471                            versionParts[1]++;
1472                    }
1473    
1474                    return versionParts[0] + StringPool.PERIOD + versionParts[1];
1475            }
1476    
1477            protected File getSmallImageFile(DDMTemplate template) {
1478                    File smallImageFile = null;
1479    
1480                    if (template.isSmallImage() &&
1481                            Validator.isNull(template.getSmallImageURL())) {
1482    
1483                            Image smallImage = ImageUtil.fetchByPrimaryKey(
1484                                    template.getSmallImageId());
1485    
1486                            if (smallImage != null) {
1487                                    smallImageFile = FileUtil.createTempFile(smallImage.getType());
1488    
1489                                    try {
1490                                            FileUtil.write(smallImageFile, smallImage.getTextObj());
1491                                    }
1492                                    catch (IOException ioe) {
1493                                            _log.error(ioe, ioe);
1494                                    }
1495                            }
1496                    }
1497    
1498                    return smallImageFile;
1499            }
1500    
1501            protected void saveImages(
1502                            boolean smallImage, long smallImageId, File smallImageFile,
1503                            byte[] smallImageBytes)
1504                    throws PortalException {
1505    
1506                    if (smallImage) {
1507                            if ((smallImageFile != null) && (smallImageBytes != null)) {
1508                                    imageLocalService.updateImage(smallImageId, smallImageBytes);
1509                            }
1510                    }
1511                    else {
1512                            imageLocalService.deleteImage(smallImageId);
1513                    }
1514            }
1515    
1516            protected void validate(
1517                            long groupId, long classNameId, String templateKey,
1518                            Map<Locale, String> nameMap, String script, boolean smallImage,
1519                            String smallImageURL, File smallImageFile, byte[] smallImageBytes)
1520                    throws PortalException {
1521    
1522                    templateKey = StringUtil.toUpperCase(templateKey.trim());
1523    
1524                    DDMTemplate template = ddmTemplatePersistence.fetchByG_C_T(
1525                            groupId, classNameId, templateKey);
1526    
1527                    if (template != null) {
1528                            throw new TemplateDuplicateTemplateKeyException(
1529                                    "Template already exists with template key " + templateKey);
1530                    }
1531    
1532                    validate(
1533                            nameMap, script, smallImage, smallImageURL, smallImageFile,
1534                            smallImageBytes);
1535            }
1536    
1537            protected void validate(Map<Locale, String> nameMap, String script)
1538                    throws PortalException {
1539    
1540                    validateName(nameMap);
1541    
1542                    if (Validator.isNull(script)) {
1543                            throw new TemplateScriptException("Script is null");
1544                    }
1545            }
1546    
1547            protected void validate(
1548                            Map<Locale, String> nameMap, String script, boolean smallImage,
1549                            String smallImageURL, File smallImageFile, byte[] smallImageBytes)
1550                    throws PortalException {
1551    
1552                    validate(nameMap, script);
1553    
1554                    String[] imageExtensions = PrefsPropsUtil.getStringArray(
1555                            PropsKeys.DYNAMIC_DATA_MAPPING_IMAGE_EXTENSIONS, StringPool.COMMA);
1556    
1557                    if (!smallImage || Validator.isNotNull(smallImageURL) ||
1558                            (smallImageFile == null) || (smallImageBytes == null)) {
1559    
1560                            return;
1561                    }
1562    
1563                    String smallImageName = smallImageFile.getName();
1564    
1565                    boolean validSmallImageExtension = false;
1566    
1567                    for (String imageExtension : imageExtensions) {
1568                            if (StringPool.STAR.equals(imageExtension) ||
1569                                    StringUtil.endsWith(
1570                                            smallImageName, imageExtension)) {
1571    
1572                                    validSmallImageExtension = true;
1573    
1574                                    break;
1575                            }
1576                    }
1577    
1578                    if (!validSmallImageExtension) {
1579                            throw new TemplateSmallImageNameException(smallImageName);
1580                    }
1581    
1582                    long smallImageMaxSize = PrefsPropsUtil.getLong(
1583                            PropsKeys.DYNAMIC_DATA_MAPPING_IMAGE_SMALL_MAX_SIZE);
1584    
1585                    if ((smallImageMaxSize > 0) &&
1586                            (smallImageBytes.length > smallImageMaxSize)) {
1587    
1588                            throw new TemplateSmallImageSizeException(
1589                                    "Image " + smallImageName + " has " + smallImageBytes.length +
1590                                            " bytes and exceeds the maximum size of " +
1591                                                    smallImageMaxSize);
1592                    }
1593            }
1594    
1595            protected void validateName(Map<Locale, String> nameMap)
1596                    throws PortalException {
1597    
1598                    String name = nameMap.get(LocaleUtil.getSiteDefault());
1599    
1600                    if (Validator.isNull(name)) {
1601                            throw new TemplateNameException("Name is null");
1602                    }
1603            }
1604    
1605            private static final Log _log = LogFactoryUtil.getLog(
1606                    DDMTemplateLocalServiceImpl.class);
1607    
1608    }