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