001    /**
002     * Copyright (c) 2000-2010 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.journal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.OrderByComparator;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.kernel.xml.Document;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portal.model.ResourceConstants;
030    import com.liferay.portal.model.User;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portlet.expando.model.ExpandoBridge;
033    import com.liferay.portlet.journal.DuplicateStructureIdException;
034    import com.liferay.portlet.journal.NoSuchStructureException;
035    import com.liferay.portlet.journal.RequiredStructureException;
036    import com.liferay.portlet.journal.StructureDescriptionException;
037    import com.liferay.portlet.journal.StructureIdException;
038    import com.liferay.portlet.journal.StructureInheritanceException;
039    import com.liferay.portlet.journal.StructureNameException;
040    import com.liferay.portlet.journal.StructureXsdException;
041    import com.liferay.portlet.journal.model.JournalStructure;
042    import com.liferay.portlet.journal.model.JournalStructureConstants;
043    import com.liferay.portlet.journal.service.base.JournalStructureLocalServiceBaseImpl;
044    import com.liferay.portlet.journal.util.JournalUtil;
045    
046    import java.util.Date;
047    import java.util.HashSet;
048    import java.util.List;
049    import java.util.Set;
050    
051    /**
052     * @author Brian Wing Shun Chan
053     * @author Raymond Augé
054     */
055    public class JournalStructureLocalServiceImpl
056            extends JournalStructureLocalServiceBaseImpl {
057    
058            public JournalStructure addStructure(
059                            long userId, long groupId, String structureId,
060                            boolean autoStructureId, String parentStructureId,
061                            String name, String description, String xsd,
062                            ServiceContext serviceContext)
063                    throws PortalException, SystemException {
064    
065                    // Structure
066    
067                    User user = userPersistence.findByPrimaryKey(userId);
068                    structureId = structureId.trim().toUpperCase();
069                    Date now = new Date();
070    
071                    try {
072                            xsd = JournalUtil.formatXML(xsd);
073                    }
074                    catch (Exception e) {
075                            throw new StructureXsdException();
076                    }
077    
078                    if (autoStructureId) {
079                            structureId = String.valueOf(counterLocalService.increment());
080                    }
081    
082                    validate(
083                            groupId, structureId, autoStructureId, parentStructureId, name,
084                            description, xsd);
085    
086                    long id = counterLocalService.increment();
087    
088                    JournalStructure structure = journalStructurePersistence.create(id);
089    
090                    structure.setUuid(serviceContext.getUuid());
091                    structure.setGroupId(groupId);
092                    structure.setCompanyId(user.getCompanyId());
093                    structure.setUserId(user.getUserId());
094                    structure.setUserName(user.getFullName());
095                    structure.setCreateDate(serviceContext.getCreateDate(now));
096                    structure.setModifiedDate(serviceContext.getModifiedDate(now));
097                    structure.setStructureId(structureId);
098                    structure.setParentStructureId(parentStructureId);
099                    structure.setName(name);
100                    structure.setDescription(description);
101                    structure.setXsd(xsd);
102    
103                    journalStructurePersistence.update(structure, false);
104    
105                    // Resources
106    
107                    if (serviceContext.getAddCommunityPermissions() ||
108                            serviceContext.getAddGuestPermissions()) {
109    
110                            addStructureResources(
111                                    structure, serviceContext.getAddCommunityPermissions(),
112                                    serviceContext.getAddGuestPermissions());
113                    }
114                    else {
115                            addStructureResources(
116                                    structure, serviceContext.getCommunityPermissions(),
117                                    serviceContext.getGuestPermissions());
118                    }
119    
120                    // Expando
121    
122                    ExpandoBridge expandoBridge = structure.getExpandoBridge();
123    
124                    expandoBridge.setAttributes(serviceContext);
125    
126                    return structure;
127            }
128    
129            public void addStructureResources(
130                            long groupId, String structureId, boolean addCommunityPermissions,
131                            boolean addGuestPermissions)
132                    throws PortalException, SystemException {
133    
134                    JournalStructure structure = journalStructurePersistence.findByG_S(
135                            groupId, structureId);
136    
137                    addStructureResources(
138                            structure, addCommunityPermissions, addGuestPermissions);
139            }
140    
141            public void addStructureResources(
142                            JournalStructure structure, boolean addCommunityPermissions,
143                            boolean addGuestPermissions)
144                    throws PortalException, SystemException {
145    
146                    resourceLocalService.addResources(
147                            structure.getCompanyId(), structure.getGroupId(),
148                            structure.getUserId(), JournalStructure.class.getName(),
149                            structure.getId(), false, addCommunityPermissions,
150                            addGuestPermissions);
151            }
152    
153            public void addStructureResources(
154                            long groupId, String structureId, String[] communityPermissions,
155                            String[] guestPermissions)
156                    throws PortalException, SystemException {
157    
158                    JournalStructure structure = journalStructurePersistence.findByG_S(
159                            groupId, structureId);
160    
161                    addStructureResources(
162                            structure, communityPermissions, guestPermissions);
163            }
164    
165            public void addStructureResources(
166                            JournalStructure structure, String[] communityPermissions,
167                            String[] guestPermissions)
168                    throws PortalException, SystemException {
169    
170                    resourceLocalService.addModelResources(
171                            structure.getCompanyId(), structure.getGroupId(),
172                            structure.getUserId(), JournalStructure.class.getName(),
173                            structure.getId(), communityPermissions, guestPermissions);
174            }
175    
176            public void checkNewLine(long groupId, String structureId)
177                    throws PortalException, SystemException {
178    
179                    JournalStructure structure = journalStructurePersistence.findByG_S(
180                            groupId, structureId);
181    
182                    String xsd = structure.getXsd();
183    
184                    if ((xsd != null) && (xsd.indexOf("\\n") != -1)) {
185                            xsd = StringUtil.replace(
186                                    xsd,
187                                    new String[] {"\\n", "\\r"},
188                                    new String[] {"\n", "\r"});
189    
190                            structure.setXsd(xsd);
191    
192                            journalStructurePersistence.update(structure, false);
193                    }
194            }
195    
196            public JournalStructure copyStructure(
197                            long userId, long groupId, String oldStructureId,
198                            String newStructureId, boolean autoStructureId)
199                    throws PortalException, SystemException {
200    
201                    // Structure
202    
203                    User user = userPersistence.findByPrimaryKey(userId);
204                    oldStructureId = oldStructureId.trim().toUpperCase();
205                    newStructureId = newStructureId.trim().toUpperCase();
206                    Date now = new Date();
207    
208                    JournalStructure oldStructure = journalStructurePersistence.findByG_S(
209                            groupId, oldStructureId);
210    
211                    if (autoStructureId) {
212                            newStructureId = String.valueOf(counterLocalService.increment());
213                    }
214                    else {
215                            validateStructureId(newStructureId);
216    
217                            JournalStructure newStructure =
218                                    journalStructurePersistence.fetchByG_S(groupId, newStructureId);
219    
220                            if (newStructure != null) {
221                                    throw new DuplicateStructureIdException();
222                            }
223                    }
224    
225                    long id = counterLocalService.increment();
226    
227                    JournalStructure newStructure = journalStructurePersistence.create(id);
228    
229                    newStructure.setGroupId(groupId);
230                    newStructure.setCompanyId(user.getCompanyId());
231                    newStructure.setUserId(user.getUserId());
232                    newStructure.setUserName(user.getFullName());
233                    newStructure.setCreateDate(now);
234                    newStructure.setModifiedDate(now);
235                    newStructure.setStructureId(newStructureId);
236                    newStructure.setName(oldStructure.getName());
237                    newStructure.setDescription(oldStructure.getDescription());
238                    newStructure.setXsd(oldStructure.getXsd());
239    
240                    journalStructurePersistence.update(newStructure, false);
241    
242                    // Resources
243    
244                    addStructureResources(newStructure, true, true);
245    
246                    return newStructure;
247            }
248    
249            public void deleteStructure(long groupId, String structureId)
250                    throws PortalException, SystemException {
251    
252                    structureId = structureId.trim().toUpperCase();
253    
254                    JournalStructure structure = journalStructurePersistence.findByG_S(
255                            groupId, structureId);
256    
257                    deleteStructure(structure);
258            }
259    
260            public void deleteStructure(JournalStructure structure)
261                    throws PortalException, SystemException {
262    
263                    if (journalArticlePersistence.countByG_S(
264                                    structure.getGroupId(), structure.getStructureId()) > 0) {
265    
266                            throw new RequiredStructureException();
267                    }
268    
269                    if (journalStructurePersistence.countByG_P(
270                                    structure.getGroupId(), structure.getStructureId()) > 0) {
271    
272                            throw new RequiredStructureException();
273                    }
274    
275                    if (journalTemplatePersistence.countByG_S(
276                                    structure.getGroupId(), structure.getStructureId()) > 0) {
277    
278                            throw new RequiredStructureException();
279                    }
280    
281                    // WebDAVProps
282    
283                    webDAVPropsLocalService.deleteWebDAVProps(
284                            JournalStructure.class.getName(), structure.getId());
285    
286                    // Expando
287    
288                    expandoValueLocalService.deleteValues(
289                            JournalStructure.class.getName(), structure.getId());
290    
291                    // Resources
292    
293                    resourceLocalService.deleteResource(
294                            structure.getCompanyId(), JournalStructure.class.getName(),
295                            ResourceConstants.SCOPE_INDIVIDUAL, structure.getId());
296    
297                    // Structure
298    
299                    journalStructurePersistence.remove(structure);
300            }
301    
302            public void deleteStructures(long groupId)
303                    throws PortalException, SystemException {
304    
305                    for (JournalStructure structure :
306                                    journalStructurePersistence.findByGroupId(groupId)) {
307    
308                            deleteStructure(structure);
309                    }
310            }
311    
312            public JournalStructure getStructure(long id)
313                    throws PortalException, SystemException {
314    
315                    return journalStructurePersistence.findByPrimaryKey(id);
316            }
317    
318            public JournalStructure getStructure(long groupId, String structureId)
319                    throws PortalException, SystemException {
320    
321                    structureId = structureId.trim().toUpperCase();
322    
323                    if (groupId == 0) {
324                            _log.error(
325                                    "No group id was passed for " + structureId + ". Group id is " +
326                                            "required since 4.2.0. Please update all custom code and " +
327                                                    "data that references structures without a group id.");
328    
329                            List<JournalStructure> structures =
330                                    journalStructurePersistence.findByStructureId(structureId);
331    
332                            if (structures.size() == 0) {
333                                    throw new NoSuchStructureException(
334                                            "No JournalStructure exists with the structure id " +
335                                                    structureId);
336                            }
337                            else {
338                                    return structures.get(0);
339                            }
340                    }
341                    else {
342                            return journalStructurePersistence.findByG_S(groupId, structureId);
343                    }
344            }
345    
346            public List<JournalStructure> getStructures() throws SystemException {
347                    return journalStructurePersistence.findAll();
348            }
349    
350            public List<JournalStructure> getStructures(long groupId)
351                    throws SystemException {
352    
353                    return journalStructurePersistence.findByGroupId(groupId);
354            }
355    
356            public List<JournalStructure> getStructures(
357                            long groupId, int start, int end)
358                    throws SystemException {
359    
360                    return journalStructurePersistence.findByGroupId(groupId, start, end);
361            }
362    
363            public int getStructuresCount(long groupId) throws SystemException {
364                    return journalStructurePersistence.countByGroupId(groupId);
365            }
366    
367            public List<JournalStructure> search(
368                            long companyId, long groupId, String keywords, int start, int end,
369                            OrderByComparator obc)
370                    throws SystemException {
371    
372                    return journalStructureFinder.findByKeywords(
373                            companyId, groupId, keywords, start, end, obc);
374            }
375    
376            public List<JournalStructure> search(
377                            long companyId, long groupId, String structureId, String name,
378                            String description, boolean andOperator, int start, int end,
379                            OrderByComparator obc)
380                    throws SystemException {
381    
382                    return journalStructureFinder.findByC_G_S_N_D(
383                            companyId, groupId, structureId, name, description, andOperator,
384                            start, end, obc);
385            }
386    
387            public int searchCount(long companyId, long groupId, String keywords)
388                    throws SystemException {
389    
390                    return journalStructureFinder.countByKeywords(
391                            companyId, groupId, keywords);
392            }
393    
394            public int searchCount(
395                            long companyId, long groupId, String structureId, String name,
396                            String description, boolean andOperator)
397                    throws SystemException {
398    
399                    return journalStructureFinder.countByC_G_S_N_D(
400                            companyId, groupId, structureId, name, description, andOperator);
401            }
402    
403            public JournalStructure updateStructure(
404                            long groupId, String structureId, String parentStructureId,
405                            String name, String description, String xsd,
406                            ServiceContext serviceContext)
407                    throws PortalException, SystemException {
408    
409                    structureId = structureId.trim().toUpperCase();
410    
411                    try {
412                            xsd = JournalUtil.formatXML(xsd);
413                    }
414                    catch (Exception e) {
415                            throw new StructureXsdException();
416                    }
417    
418                    validateParentStructureId(groupId, structureId, parentStructureId);
419                    validate(name, description, xsd);
420    
421                    JournalStructure structure = journalStructurePersistence.findByG_S(
422                            groupId, structureId);
423    
424                    structure.setModifiedDate(serviceContext.getModifiedDate(null));
425                    structure.setParentStructureId(parentStructureId);
426                    structure.setName(name);
427                    structure.setDescription(description);
428                    structure.setXsd(xsd);
429    
430                    journalStructurePersistence.update(structure, false);
431    
432                    // Expando
433    
434                    ExpandoBridge expandoBridge = structure.getExpandoBridge();
435    
436                    expandoBridge.setAttributes(serviceContext);
437    
438                    return structure;
439            }
440    
441            protected void validate(
442                            long groupId, String structureId, boolean autoStructureId,
443                            String parentStructureId, String name, String description,
444                            String xsd)
445                    throws PortalException, SystemException {
446    
447                    if (!autoStructureId) {
448                            validateStructureId(structureId);
449    
450                            JournalStructure structure = journalStructurePersistence.fetchByG_S(
451                                    groupId, structureId);
452    
453                            if (structure != null) {
454                                    throw new DuplicateStructureIdException();
455                            }
456                    }
457    
458                    validateParentStructureId(groupId, structureId, parentStructureId);
459                    validate(name, description, xsd);
460            }
461    
462            protected void validate(String name, String description, String xsd)
463                    throws PortalException {
464    
465                    if (Validator.isNull(name)) {
466                            throw new StructureNameException();
467                    }
468                    else if (Validator.isNull(description)) {
469                            throw new StructureDescriptionException();
470                    }
471    
472                    if (Validator.isNull(xsd)) {
473                            throw new StructureXsdException();
474                    }
475                    else {
476                            try {
477                                    Document doc = SAXReaderUtil.read(xsd);
478    
479                                    Element root = doc.getRootElement();
480    
481                                    List<Element> children = root.elements();
482    
483                                    if (children.size() == 0) {
484                                            throw new StructureXsdException();
485                                    }
486    
487                                    Set<String> elNames = new HashSet<String>();
488    
489                                    validate(children, elNames);
490                            }
491                            catch (Exception e) {
492                                    throw new StructureXsdException();
493                            }
494                    }
495            }
496    
497            protected void validate(List<Element> children, Set<String> elNames)
498                    throws PortalException {
499    
500                    for (Element el : children) {
501                            if (el.getName().equals("meta-data")) {
502                                    continue;
503                            }
504    
505                            String elName = el.attributeValue("name", StringPool.BLANK);
506                            String elType = el.attributeValue("type", StringPool.BLANK);
507    
508                            if (Validator.isNull(elName) ||
509                                    elName.startsWith(JournalStructureConstants.RESERVED)) {
510    
511                                    throw new StructureXsdException();
512                            }
513                            else {
514                                    char[] c = elName.toCharArray();
515    
516                                    for (int i = 0; i < c.length; i++) {
517                                            if ((!Validator.isChar(c[i])) &&
518                                                    (!Validator.isDigit(c[i])) && (c[i] != CharPool.DASH) &&
519                                                    (c[i] != CharPool.UNDERLINE)) {
520    
521                                                    throw new StructureXsdException();
522                                            }
523                                    }
524    
525                                    String completePath = elName;
526    
527                                    Element parent = el.getParent();
528    
529                                    while (!parent.isRootElement()) {
530                                            completePath =
531                                                    parent.attributeValue("name", StringPool.BLANK) +
532                                                            StringPool.SLASH + completePath;
533    
534                                            parent = parent.getParent();
535                                    }
536    
537                                    String elNameLowerCase = completePath.toLowerCase();
538    
539                                    if (elNames.contains(elNameLowerCase)) {
540                                            throw new StructureXsdException();
541                                    }
542                                    else {
543                                            elNames.add(elNameLowerCase);
544                                    }
545                            }
546    
547                            if (Validator.isNull(elType)) {
548                                    throw new StructureXsdException();
549                            }
550    
551                            validate(el.elements(), elNames);
552                    }
553            }
554    
555            protected void validateParentStructureId(
556                            long groupId, String structureId, String parentStructureId)
557                    throws PortalException, SystemException {
558    
559                    if (Validator.isNull(parentStructureId)) {
560                            return;
561                    }
562    
563                    if (parentStructureId.equals(structureId)) {
564                            throw new StructureInheritanceException();
565                    }
566    
567                    JournalStructure parentStructure =
568                            journalStructurePersistence.fetchByG_S(groupId, parentStructureId);
569    
570                    while (parentStructure != null) {
571                            if ((parentStructure != null) &&
572                                    (parentStructure.getStructureId().equals(structureId)) ||
573                                    (parentStructure.getParentStructureId().equals(
574                                            structureId))) {
575    
576                                    throw new StructureInheritanceException();
577                            }
578    
579                            parentStructure = journalStructurePersistence.fetchByG_S(
580                                    groupId, parentStructure.getParentStructureId());
581                    }
582            }
583    
584            protected void validateStructureId(String structureId)
585                    throws PortalException {
586    
587                    if ((Validator.isNull(structureId)) ||
588                            (Validator.isNumber(structureId)) ||
589                            (structureId.indexOf(StringPool.SPACE) != -1)) {
590    
591                            throw new StructureIdException();
592                    }
593            }
594    
595            private static Log _log = LogFactoryUtil.getLog(
596                    JournalStructureLocalServiceImpl.class);
597    
598    }