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