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