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