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