1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.journal.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.CharPool;
30  import com.liferay.portal.kernel.util.OrderByComparator;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Validator;
34  import com.liferay.portal.kernel.xml.Document;
35  import com.liferay.portal.kernel.xml.Element;
36  import com.liferay.portal.kernel.xml.SAXReaderUtil;
37  import com.liferay.portal.model.ResourceConstants;
38  import com.liferay.portal.model.User;
39  import com.liferay.portlet.journal.DuplicateStructureIdException;
40  import com.liferay.portlet.journal.NoSuchStructureException;
41  import com.liferay.portlet.journal.RequiredStructureException;
42  import com.liferay.portlet.journal.StructureDescriptionException;
43  import com.liferay.portlet.journal.StructureIdException;
44  import com.liferay.portlet.journal.StructureInheritanceException;
45  import com.liferay.portlet.journal.StructureNameException;
46  import com.liferay.portlet.journal.StructureXsdException;
47  import com.liferay.portlet.journal.model.JournalStructure;
48  import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
49  import com.liferay.portlet.journal.service.base.JournalStructureLocalServiceBaseImpl;
50  import com.liferay.portlet.journal.util.JournalUtil;
51  
52  import java.util.Date;
53  import java.util.HashSet;
54  import java.util.List;
55  import java.util.Set;
56  
57  /**
58   * <a href="JournalStructureLocalServiceImpl.java.html"><b><i>View Source</i>
59   * </b></a>
60   *
61   * @author Brian Wing Shun Chan
62   *
63   */
64  public class JournalStructureLocalServiceImpl
65      extends JournalStructureLocalServiceBaseImpl {
66  
67      public JournalStructure addStructure(
68              long userId, long groupId, String structureId,
69              boolean autoStructureId, String parentStructureId, String name,
70              String description, String xsd, boolean addCommunityPermissions,
71              boolean addGuestPermissions)
72          throws PortalException, SystemException {
73  
74          return addStructure(
75              null, userId, groupId, structureId, autoStructureId,
76              parentStructureId, name, description, xsd,
77              Boolean.valueOf(addCommunityPermissions),
78              Boolean.valueOf(addGuestPermissions), null, null);
79      }
80  
81      public JournalStructure addStructure(
82              String uuid, long userId, long groupId, String structureId,
83              boolean autoStructureId, String parentStructureId, String name,
84              String description, String xsd, boolean addCommunityPermissions,
85              boolean addGuestPermissions)
86          throws PortalException, SystemException {
87  
88          return addStructure(
89              uuid, userId, groupId, structureId, autoStructureId,
90              parentStructureId, name, description, xsd,
91              Boolean.valueOf(addCommunityPermissions),
92              Boolean.valueOf(addGuestPermissions), null, null);
93      }
94  
95      public JournalStructure addStructure(
96              long userId, long groupId, String structureId,
97              boolean autoStructureId, String parentStructureId, String name,
98              String description, String xsd, String[] communityPermissions,
99              String[] guestPermissions)
100         throws PortalException, SystemException {
101 
102         return addStructure(
103             null, userId, groupId, structureId, autoStructureId,
104             parentStructureId, name, description, xsd, null, null,
105             communityPermissions, guestPermissions);
106     }
107 
108     public JournalStructure addStructure(
109             String uuid, long userId, long groupId, String structureId,
110             boolean autoStructureId, String parentStructureId,
111             String name, String description, String xsd,
112             Boolean addCommunityPermissions, Boolean addGuestPermissions,
113             String[] communityPermissions, String[] guestPermissions)
114         throws PortalException, SystemException {
115 
116         // Structure
117 
118         User user = userPersistence.findByPrimaryKey(userId);
119         structureId = structureId.trim().toUpperCase();
120         Date now = new Date();
121 
122         try {
123             xsd = JournalUtil.formatXML(xsd);
124         }
125         catch (Exception e) {
126             throw new StructureXsdException();
127         }
128 
129         validate(
130             groupId, structureId, autoStructureId, parentStructureId, name,
131             description, xsd);
132 
133         if (autoStructureId) {
134             structureId = String.valueOf(counterLocalService.increment());
135         }
136 
137         long id = counterLocalService.increment();
138 
139         JournalStructure structure = journalStructurePersistence.create(id);
140 
141         structure.setUuid(uuid);
142         structure.setGroupId(groupId);
143         structure.setCompanyId(user.getCompanyId());
144         structure.setUserId(user.getUserId());
145         structure.setUserName(user.getFullName());
146         structure.setCreateDate(now);
147         structure.setModifiedDate(now);
148         structure.setStructureId(structureId);
149         structure.setParentStructureId(parentStructureId);
150         structure.setName(name);
151         structure.setDescription(description);
152         structure.setXsd(xsd);
153 
154         journalStructurePersistence.update(structure, false);
155 
156         // Resources
157 
158         if ((addCommunityPermissions != null) &&
159             (addGuestPermissions != null)) {
160 
161             addStructureResources(
162                 structure, addCommunityPermissions.booleanValue(),
163                 addGuestPermissions.booleanValue());
164         }
165         else {
166             addStructureResources(
167                 structure, communityPermissions, guestPermissions);
168         }
169 
170         return structure;
171     }
172 
173     public void addStructureResources(
174             long groupId, String structureId, boolean addCommunityPermissions,
175             boolean addGuestPermissions)
176         throws PortalException, SystemException {
177 
178         JournalStructure structure = journalStructurePersistence.findByG_S(
179             groupId, structureId);
180 
181         addStructureResources(
182             structure, addCommunityPermissions, addGuestPermissions);
183     }
184 
185     public void addStructureResources(
186             JournalStructure structure, boolean addCommunityPermissions,
187             boolean addGuestPermissions)
188         throws PortalException, SystemException {
189 
190         resourceLocalService.addResources(
191             structure.getCompanyId(), structure.getGroupId(),
192             structure.getUserId(), JournalStructure.class.getName(),
193             structure.getId(), false, addCommunityPermissions,
194             addGuestPermissions);
195     }
196 
197     public void addStructureResources(
198             long groupId, String structureId, String[] communityPermissions,
199             String[] guestPermissions)
200         throws PortalException, SystemException {
201 
202         JournalStructure structure = journalStructurePersistence.findByG_S(
203             groupId, structureId);
204 
205         addStructureResources(
206             structure, communityPermissions, guestPermissions);
207     }
208 
209     public void addStructureResources(
210             JournalStructure structure, String[] communityPermissions,
211             String[] guestPermissions)
212         throws PortalException, SystemException {
213 
214         resourceLocalService.addModelResources(
215             structure.getCompanyId(), structure.getGroupId(),
216             structure.getUserId(), JournalStructure.class.getName(),
217             structure.getId(), communityPermissions, guestPermissions);
218     }
219 
220     public void checkNewLine(long groupId, String structureId)
221         throws PortalException, SystemException {
222 
223         JournalStructure structure = journalStructurePersistence.findByG_S(
224             groupId, structureId);
225 
226         String xsd = structure.getXsd();
227 
228         if ((xsd != null) && (xsd.indexOf("\\n") != -1)) {
229             xsd = StringUtil.replace(
230                 xsd,
231                 new String[] {"\\n", "\\r"},
232                 new String[] {"\n", "\r"});
233 
234             structure.setXsd(xsd);
235 
236             journalStructurePersistence.update(structure, false);
237         }
238     }
239 
240     public JournalStructure copyStructure(
241             long userId, long groupId, String oldStructureId,
242             String newStructureId, boolean autoStructureId)
243         throws PortalException, SystemException {
244 
245         // Structure
246 
247         User user = userPersistence.findByPrimaryKey(userId);
248         oldStructureId = oldStructureId.trim().toUpperCase();
249         newStructureId = newStructureId.trim().toUpperCase();
250         Date now = new Date();
251 
252         JournalStructure oldStructure = journalStructurePersistence.findByG_S(
253             groupId, oldStructureId);
254 
255         if (autoStructureId) {
256             newStructureId = String.valueOf(counterLocalService.increment());
257         }
258         else {
259             validateStructureId(newStructureId);
260 
261             JournalStructure newStructure =
262                 journalStructurePersistence.fetchByG_S(groupId, newStructureId);
263 
264             if (newStructure != null) {
265                 throw new DuplicateStructureIdException();
266             }
267         }
268 
269         long id = counterLocalService.increment();
270 
271         JournalStructure newStructure = journalStructurePersistence.create(id);
272 
273         newStructure.setGroupId(groupId);
274         newStructure.setCompanyId(user.getCompanyId());
275         newStructure.setUserId(user.getUserId());
276         newStructure.setUserName(user.getFullName());
277         newStructure.setCreateDate(now);
278         newStructure.setModifiedDate(now);
279         newStructure.setStructureId(newStructureId);
280         newStructure.setName(oldStructure.getName());
281         newStructure.setDescription(oldStructure.getDescription());
282         newStructure.setXsd(oldStructure.getXsd());
283 
284         journalStructurePersistence.update(newStructure, false);
285 
286         // Resources
287 
288         addStructureResources(newStructure, true, true);
289 
290         return newStructure;
291     }
292 
293     public void deleteStructure(long groupId, String structureId)
294         throws PortalException, SystemException {
295 
296         structureId = structureId.trim().toUpperCase();
297 
298         JournalStructure structure = journalStructurePersistence.findByG_S(
299             groupId, structureId);
300 
301         deleteStructure(structure);
302     }
303 
304     public void deleteStructure(JournalStructure structure)
305         throws PortalException, SystemException {
306 
307         if (journalArticlePersistence.countByG_S(
308                 structure.getGroupId(), structure.getStructureId()) > 0) {
309 
310             throw new RequiredStructureException();
311         }
312 
313         if (journalStructurePersistence.countByG_P(
314                 structure.getGroupId(), structure.getStructureId()) > 0) {
315 
316             throw new RequiredStructureException();
317         }
318 
319         if (journalTemplatePersistence.countByG_S(
320                 structure.getGroupId(), structure.getStructureId()) > 0) {
321 
322             throw new RequiredStructureException();
323         }
324 
325         // WebDAVProps
326 
327         webDAVPropsLocalService.deleteWebDAVProps(
328             JournalStructure.class.getName(), structure.getPrimaryKey());
329 
330         // Resources
331 
332         resourceLocalService.deleteResource(
333             structure.getCompanyId(), JournalStructure.class.getName(),
334             ResourceConstants.SCOPE_INDIVIDUAL, structure.getId());
335 
336         // Structure
337 
338         journalStructurePersistence.remove(structure);
339     }
340 
341     public void deleteStructures(long groupId)
342         throws PortalException, SystemException {
343 
344         for (JournalStructure structure :
345                 journalStructurePersistence.findByGroupId(groupId)) {
346 
347             deleteStructure(structure);
348         }
349     }
350 
351     public JournalStructure getStructure(long id)
352         throws PortalException, SystemException {
353 
354         return journalStructurePersistence.findByPrimaryKey(id);
355     }
356 
357     public JournalStructure getStructure(long groupId, String structureId)
358         throws PortalException, SystemException {
359 
360         structureId = structureId.trim().toUpperCase();
361 
362         if (groupId == 0) {
363             _log.error(
364                 "No group id was passed for " + structureId + ". Group id is " +
365                     "required since 4.2.0. Please update all custom code and " +
366                         "data that references structures without a group id.");
367 
368             List<JournalStructure> structures =
369                 journalStructurePersistence.findByStructureId(structureId);
370 
371             if (structures.size() == 0) {
372                 throw new NoSuchStructureException(
373                     "No JournalStructure exists with the structure id " +
374                         structureId);
375             }
376             else {
377                 return structures.get(0);
378             }
379         }
380         else {
381             return journalStructurePersistence.findByG_S(groupId, structureId);
382         }
383     }
384 
385     public List<JournalStructure> getStructures() throws SystemException {
386         return journalStructurePersistence.findAll();
387     }
388 
389     public List<JournalStructure> getStructures(long groupId)
390         throws SystemException {
391 
392         return journalStructurePersistence.findByGroupId(groupId);
393     }
394 
395     public List<JournalStructure> getStructures(
396             long groupId, int start, int end)
397         throws SystemException {
398 
399         return journalStructurePersistence.findByGroupId(groupId, start, end);
400     }
401 
402     public int getStructuresCount(long groupId) throws SystemException {
403         return journalStructurePersistence.countByGroupId(groupId);
404     }
405 
406     public List<JournalStructure> search(
407             long companyId, long groupId, String keywords, int start, int end,
408             OrderByComparator obc)
409         throws SystemException {
410 
411         return journalStructureFinder.findByKeywords(
412             companyId, groupId, keywords, start, end, obc);
413     }
414 
415     public List<JournalStructure> search(
416             long companyId, long groupId, String structureId, String name,
417             String description, boolean andOperator, int start, int end,
418             OrderByComparator obc)
419         throws SystemException {
420 
421         return journalStructureFinder.findByC_G_S_N_D(
422             companyId, groupId, structureId, name, description, andOperator,
423             start, end, obc);
424     }
425 
426     public int searchCount(long companyId, long groupId, String keywords)
427         throws SystemException {
428 
429         return journalStructureFinder.countByKeywords(
430             companyId, groupId, keywords);
431     }
432 
433     public int searchCount(
434             long companyId, long groupId, String structureId, String name,
435             String description, boolean andOperator)
436         throws SystemException {
437 
438         return journalStructureFinder.countByC_G_S_N_D(
439             companyId, groupId, structureId, name, description, andOperator);
440     }
441 
442     public JournalStructure updateStructure(
443             long groupId, String structureId, String parentStructureId,
444             String name, String description, String xsd)
445         throws PortalException, SystemException {
446 
447         structureId = structureId.trim().toUpperCase();
448 
449         try {
450             xsd = JournalUtil.formatXML(xsd);
451         }
452         catch (Exception e) {
453             throw new StructureXsdException();
454         }
455 
456         validateParentStructureId(groupId, structureId, parentStructureId);
457         validate(name, description, xsd);
458 
459         JournalStructure structure = journalStructurePersistence.findByG_S(
460             groupId, structureId);
461 
462         structure.setModifiedDate(new Date());
463         structure.setParentStructureId(parentStructureId);
464         structure.setName(name);
465         structure.setDescription(description);
466         structure.setXsd(xsd);
467 
468         journalStructurePersistence.update(structure, false);
469 
470         return structure;
471     }
472 
473     protected void validate(
474             long groupId, String structureId, boolean autoStructureId,
475             String parentStructureId, String name, String description,
476             String xsd)
477         throws PortalException, SystemException {
478 
479         if (!autoStructureId) {
480             validateStructureId(structureId);
481 
482             JournalStructure structure = journalStructurePersistence.fetchByG_S(
483                 groupId, structureId);
484 
485             if (structure != null) {
486                 throw new DuplicateStructureIdException();
487             }
488         }
489 
490         validateParentStructureId(groupId, structureId, parentStructureId);
491         validate(name, description, xsd);
492     }
493 
494     protected void validate(String name, String description, String xsd)
495         throws PortalException {
496 
497         if (Validator.isNull(name)) {
498             throw new StructureNameException();
499         }
500         else if (Validator.isNull(description)) {
501             throw new StructureDescriptionException();
502         }
503 
504         if (Validator.isNull(xsd)) {
505             throw new StructureXsdException();
506         }
507         else {
508             try {
509                 Document doc = SAXReaderUtil.read(xsd);
510 
511                 Element root = doc.getRootElement();
512 
513                 List<Element> children = root.elements();
514 
515                 if (children.size() == 0) {
516                     throw new StructureXsdException();
517                 }
518 
519                 Set<String> elNames = new HashSet<String>();
520 
521                 validate(children, elNames);
522             }
523             catch (Exception e) {
524                 throw new StructureXsdException();
525             }
526         }
527     }
528 
529     protected void validate(List<Element> children, Set<String> elNames)
530         throws PortalException {
531 
532         for (Element el : children) {
533             String elName = el.attributeValue("name", StringPool.BLANK);
534             String elType = el.attributeValue("type", StringPool.BLANK);
535 
536             if (Validator.isNull(elName) ||
537                 elName.startsWith(JournalStructureImpl.RESERVED)) {
538 
539                 throw new StructureXsdException();
540             }
541             else {
542                 char[] c = elName.toCharArray();
543 
544                 for (int i = 0; i < c.length; i++) {
545                     if ((!Validator.isChar(c[i])) &&
546                         (!Validator.isDigit(c[i])) && (c[i] != CharPool.DASH) &&
547                         (c[i] != CharPool.UNDERLINE)) {
548 
549                         throw new StructureXsdException();
550                     }
551                 }
552 
553                 String completePath = elName;
554 
555                 Element parent = el.getParent();
556 
557                 while (!parent.isRootElement()) {
558                     completePath =
559                         parent.attributeValue("name", StringPool.BLANK) +
560                             StringPool.SLASH + completePath;
561 
562                     parent = parent.getParent();
563                 }
564 
565                 String elNameLowerCase = completePath.toLowerCase();
566 
567                 if (elNames.contains(elNameLowerCase)) {
568                     throw new StructureXsdException();
569                 }
570                 else {
571                     elNames.add(elNameLowerCase);
572                 }
573             }
574 
575             if (Validator.isNull(elType)) {
576                 throw new StructureXsdException();
577             }
578 
579             validate(el.elements(), elNames);
580         }
581     }
582 
583     protected void validateParentStructureId(
584             long groupId, String structureId, String parentStructureId)
585         throws PortalException, SystemException {
586 
587         if (Validator.isNull(parentStructureId)) {
588             return;
589         }
590 
591         if (parentStructureId.equals(structureId)) {
592             throw new StructureInheritanceException();
593         }
594 
595         JournalStructure parentStructure =
596             journalStructurePersistence.fetchByG_S(groupId, parentStructureId);
597 
598         while (parentStructure != null) {
599             if ((parentStructure != null) &&
600                 (parentStructure.getStructureId().equals(structureId)) ||
601                 (parentStructure.getParentStructureId().equals(
602                     structureId))) {
603 
604                 throw new StructureInheritanceException();
605             }
606 
607             parentStructure = journalStructurePersistence.fetchByG_S(
608                 groupId, parentStructure.getParentStructureId());
609         }
610     }
611 
612     protected void validateStructureId(String structureId)
613         throws PortalException {
614 
615         if ((Validator.isNull(structureId)) ||
616             (Validator.isNumber(structureId)) ||
617             (structureId.indexOf(StringPool.SPACE) != -1)) {
618 
619             throw new StructureIdException();
620         }
621     }
622 
623     private static Log _log =
624         LogFactoryUtil.getLog(JournalStructureLocalServiceImpl.class);
625 
626 }