1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
14  
15  package com.liferay.portlet.journal.service.impl;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.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.impl.JournalStructureImpl;
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(serviceContext.getCreateDate(now));
110         structure.setModifiedDate(serviceContext.getModifiedDate(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.getPrimaryKey());
299 
300         // Expando
301 
302         expandoValueLocalService.deleteValues(
303             JournalStructure.class.getName(), structure.getPrimaryKey());
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(serviceContext.getModifiedDate(null));
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             String elName = el.attributeValue("name", StringPool.BLANK);
516             String elType = el.attributeValue("type", StringPool.BLANK);
517 
518             if (Validator.isNull(elName) ||
519                 elName.startsWith(JournalStructureImpl.RESERVED)) {
520 
521                 throw new StructureXsdException();
522             }
523             else {
524                 char[] c = elName.toCharArray();
525 
526                 for (int i = 0; i < c.length; i++) {
527                     if ((!Validator.isChar(c[i])) &&
528                         (!Validator.isDigit(c[i])) && (c[i] != CharPool.DASH) &&
529                         (c[i] != CharPool.UNDERLINE)) {
530 
531                         throw new StructureXsdException();
532                     }
533                 }
534 
535                 String completePath = elName;
536 
537                 Element parent = el.getParent();
538 
539                 while (!parent.isRootElement()) {
540                     completePath =
541                         parent.attributeValue("name", StringPool.BLANK) +
542                             StringPool.SLASH + completePath;
543 
544                     parent = parent.getParent();
545                 }
546 
547                 String elNameLowerCase = completePath.toLowerCase();
548 
549                 if (elNames.contains(elNameLowerCase)) {
550                     throw new StructureXsdException();
551                 }
552                 else {
553                     elNames.add(elNameLowerCase);
554                 }
555             }
556 
557             if (Validator.isNull(elType)) {
558                 throw new StructureXsdException();
559             }
560 
561             validate(el.elements(), elNames);
562         }
563     }
564 
565     protected void validateParentStructureId(
566             long groupId, String structureId, String parentStructureId)
567         throws PortalException, SystemException {
568 
569         if (Validator.isNull(parentStructureId)) {
570             return;
571         }
572 
573         if (parentStructureId.equals(structureId)) {
574             throw new StructureInheritanceException();
575         }
576 
577         JournalStructure parentStructure =
578             journalStructurePersistence.fetchByG_S(groupId, parentStructureId);
579 
580         while (parentStructure != null) {
581             if ((parentStructure != null) &&
582                 (parentStructure.getStructureId().equals(structureId)) ||
583                 (parentStructure.getParentStructureId().equals(
584                     structureId))) {
585 
586                 throw new StructureInheritanceException();
587             }
588 
589             parentStructure = journalStructurePersistence.fetchByG_S(
590                 groupId, parentStructure.getParentStructureId());
591         }
592     }
593 
594     protected void validateStructureId(String structureId)
595         throws PortalException {
596 
597         if ((Validator.isNull(structureId)) ||
598             (Validator.isNumber(structureId)) ||
599             (structureId.indexOf(CharPool.SPACE) != -1)) {
600 
601             throw new StructureIdException();
602         }
603     }
604 
605     private static Log _log = LogFactoryUtil.getLog(
606         JournalStructureLocalServiceImpl.class);
607 
608 }