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