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