001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.journal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.CharPool;
022    import com.liferay.portal.kernel.util.OrderByComparator;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.kernel.xml.Document;
027    import com.liferay.portal.kernel.xml.Element;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portal.model.ResourceConstants;
030    import com.liferay.portal.model.User;
031    import com.liferay.portal.service.ServiceContext;
032    import com.liferay.portlet.expando.model.ExpandoBridge;
033    import com.liferay.portlet.journal.DuplicateStructureElementException;
034    import com.liferay.portlet.journal.DuplicateStructureIdException;
035    import com.liferay.portlet.journal.NoSuchStructureException;
036    import com.liferay.portlet.journal.RequiredStructureException;
037    import com.liferay.portlet.journal.StructureDescriptionException;
038    import com.liferay.portlet.journal.StructureIdException;
039    import com.liferay.portlet.journal.StructureInheritanceException;
040    import com.liferay.portlet.journal.StructureNameException;
041    import com.liferay.portlet.journal.StructureXsdException;
042    import com.liferay.portlet.journal.model.JournalStructure;
043    import com.liferay.portlet.journal.model.JournalStructureConstants;
044    import com.liferay.portlet.journal.service.base.JournalStructureLocalServiceBaseImpl;
045    import com.liferay.portlet.journal.util.JournalUtil;
046    
047    import java.util.ArrayList;
048    import java.util.Date;
049    import java.util.HashSet;
050    import java.util.List;
051    import java.util.Set;
052    
053    /**
054     * @author Brian Wing Shun Chan
055     * @author Raymond Augé
056     */
057    public class JournalStructureLocalServiceImpl
058            extends JournalStructureLocalServiceBaseImpl {
059    
060            public JournalStructure addStructure(
061                            long userId, long groupId, String structureId,
062                            boolean autoStructureId, String parentStructureId,
063                            String name, String description, String xsd,
064                            ServiceContext serviceContext)
065                    throws PortalException, SystemException {
066    
067                    // Structure
068    
069                    User user = userPersistence.findByPrimaryKey(userId);
070                    structureId = structureId.trim().toUpperCase();
071                    Date now = new Date();
072    
073                    try {
074                            xsd = JournalUtil.formatXML(xsd);
075                    }
076                    catch (Exception e) {
077                            throw new StructureXsdException();
078                    }
079    
080                    if (autoStructureId) {
081                            structureId = String.valueOf(counterLocalService.increment());
082                    }
083    
084                    validate(
085                            groupId, structureId, autoStructureId, parentStructureId, name,
086                            description, xsd);
087    
088                    long id = counterLocalService.increment();
089    
090                    JournalStructure structure = journalStructurePersistence.create(id);
091    
092                    structure.setUuid(serviceContext.getUuid());
093                    structure.setGroupId(groupId);
094                    structure.setCompanyId(user.getCompanyId());
095                    structure.setUserId(user.getUserId());
096                    structure.setUserName(user.getFullName());
097                    structure.setCreateDate(serviceContext.getCreateDate(now));
098                    structure.setModifiedDate(serviceContext.getModifiedDate(now));
099                    structure.setStructureId(structureId);
100                    structure.setParentStructureId(parentStructureId);
101                    structure.setName(name);
102                    structure.setDescription(description);
103                    structure.setXsd(xsd);
104    
105                    journalStructurePersistence.update(structure, false);
106    
107                    // Resources
108    
109                    if (serviceContext.getAddCommunityPermissions() ||
110                            serviceContext.getAddGuestPermissions()) {
111    
112                            addStructureResources(
113                                    structure, serviceContext.getAddCommunityPermissions(),
114                                    serviceContext.getAddGuestPermissions());
115                    }
116                    else {
117                            addStructureResources(
118                                    structure, serviceContext.getCommunityPermissions(),
119                                    serviceContext.getGuestPermissions());
120                    }
121    
122                    // Expando
123    
124                    ExpandoBridge expandoBridge = structure.getExpandoBridge();
125    
126                    expandoBridge.setAttributes(serviceContext);
127    
128                    return structure;
129            }
130    
131            public void addStructureResources(
132                            JournalStructure structure, boolean addCommunityPermissions,
133                            boolean addGuestPermissions)
134                    throws PortalException, SystemException {
135    
136                    resourceLocalService.addResources(
137                            structure.getCompanyId(), structure.getGroupId(),
138                            structure.getUserId(), JournalStructure.class.getName(),
139                            structure.getId(), false, addCommunityPermissions,
140                            addGuestPermissions);
141            }
142    
143            public void addStructureResources(
144                            JournalStructure structure, String[] communityPermissions,
145                            String[] guestPermissions)
146                    throws PortalException, SystemException {
147    
148                    resourceLocalService.addModelResources(
149                            structure.getCompanyId(), structure.getGroupId(),
150                            structure.getUserId(), JournalStructure.class.getName(),
151                            structure.getId(), communityPermissions, guestPermissions);
152            }
153    
154            public void addStructureResources(
155                            long groupId, String structureId, boolean addCommunityPermissions,
156                            boolean addGuestPermissions)
157                    throws PortalException, SystemException {
158    
159                    JournalStructure structure = journalStructurePersistence.findByG_S(
160                            groupId, structureId);
161    
162                    addStructureResources(
163                            structure, addCommunityPermissions, addGuestPermissions);
164            }
165    
166            public void addStructureResources(
167                            long groupId, String structureId, String[] communityPermissions,
168                            String[] guestPermissions)
169                    throws PortalException, SystemException {
170    
171                    JournalStructure structure = journalStructurePersistence.findByG_S(
172                            groupId, structureId);
173    
174                    addStructureResources(
175                            structure, communityPermissions, guestPermissions);
176            }
177    
178            public void checkNewLine(long groupId, String structureId)
179                    throws PortalException, SystemException {
180    
181                    JournalStructure structure = journalStructurePersistence.findByG_S(
182                            groupId, structureId);
183    
184                    String xsd = structure.getXsd();
185    
186                    if ((xsd != null) && (xsd.indexOf("\\n") != -1)) {
187                            xsd = StringUtil.replace(
188                                    xsd,
189                                    new String[] {"\\n", "\\r"},
190                                    new String[] {"\n", "\r"});
191    
192                            structure.setXsd(xsd);
193    
194                            journalStructurePersistence.update(structure, false);
195                    }
196            }
197    
198            public JournalStructure copyStructure(
199                            long userId, long groupId, String oldStructureId,
200                            String newStructureId, boolean autoStructureId)
201                    throws PortalException, SystemException {
202    
203                    // Structure
204    
205                    User user = userPersistence.findByPrimaryKey(userId);
206                    oldStructureId = oldStructureId.trim().toUpperCase();
207                    newStructureId = newStructureId.trim().toUpperCase();
208                    Date now = new Date();
209    
210                    JournalStructure oldStructure = journalStructurePersistence.findByG_S(
211                            groupId, oldStructureId);
212    
213                    if (autoStructureId) {
214                            newStructureId = String.valueOf(counterLocalService.increment());
215                    }
216                    else {
217                            validateStructureId(newStructureId);
218    
219                            JournalStructure newStructure =
220                                    journalStructurePersistence.fetchByG_S(groupId, newStructureId);
221    
222                            if (newStructure != null) {
223                                    throw new DuplicateStructureIdException();
224                            }
225                    }
226    
227                    long id = counterLocalService.increment();
228    
229                    JournalStructure newStructure = journalStructurePersistence.create(id);
230    
231                    newStructure.setGroupId(groupId);
232                    newStructure.setCompanyId(user.getCompanyId());
233                    newStructure.setUserId(user.getUserId());
234                    newStructure.setUserName(user.getFullName());
235                    newStructure.setCreateDate(now);
236                    newStructure.setModifiedDate(now);
237                    newStructure.setStructureId(newStructureId);
238                    newStructure.setName(oldStructure.getName());
239                    newStructure.setDescription(oldStructure.getDescription());
240                    newStructure.setXsd(oldStructure.getXsd());
241    
242                    journalStructurePersistence.update(newStructure, false);
243    
244                    // Resources
245    
246                    addStructureResources(newStructure, true, true);
247    
248                    return newStructure;
249            }
250    
251            public void deleteStructure(JournalStructure structure)
252                    throws PortalException, SystemException {
253    
254                    if (journalArticlePersistence.countByG_S(
255                                    structure.getGroupId(), structure.getStructureId()) > 0) {
256    
257                            throw new RequiredStructureException();
258                    }
259    
260                    if (journalStructurePersistence.countByG_P(
261                                    structure.getGroupId(), structure.getStructureId()) > 0) {
262    
263                            throw new RequiredStructureException();
264                    }
265    
266                    if (journalTemplatePersistence.countByG_S(
267                                    structure.getGroupId(), structure.getStructureId()) > 0) {
268    
269                            throw new RequiredStructureException();
270                    }
271    
272                    // WebDAVProps
273    
274                    webDAVPropsLocalService.deleteWebDAVProps(
275                            JournalStructure.class.getName(), structure.getId());
276    
277                    // Expando
278    
279                    expandoValueLocalService.deleteValues(
280                            JournalStructure.class.getName(), structure.getId());
281    
282                    // Resources
283    
284                    resourceLocalService.deleteResource(
285                            structure.getCompanyId(), JournalStructure.class.getName(),
286                            ResourceConstants.SCOPE_INDIVIDUAL, structure.getId());
287    
288                    // Structure
289    
290                    journalStructurePersistence.remove(structure);
291            }
292    
293            public void deleteStructure(long groupId, String structureId)
294                    throws PortalException, SystemException {
295    
296                    structureId = structureId.trim().toUpperCase();
297    
298                    JournalStructure structure = journalStructurePersistence.findByG_S(
299                            groupId, structureId);
300    
301                    deleteStructure(structure);
302            }
303    
304            public void deleteStructures(long groupId)
305                    throws PortalException, SystemException {
306    
307                    for (JournalStructure structure :
308                                    journalStructurePersistence.findByGroupId(groupId)) {
309    
310                            deleteStructure(structure);
311                    }
312            }
313    
314            public JournalStructure getStructure(long id)
315                    throws PortalException, SystemException {
316    
317                    return journalStructurePersistence.findByPrimaryKey(id);
318            }
319    
320            public JournalStructure getStructure(long groupId, String structureId)
321                    throws PortalException, SystemException {
322    
323                    structureId = structureId.trim().toUpperCase();
324    
325                    if (groupId == 0) {
326                            _log.error(
327                                    "No group id was passed for " + structureId + ". Group id is " +
328                                            "required since 4.2.0. Please update all custom code and " +
329                                                    "data that references structures without a group id.");
330    
331                            List<JournalStructure> structures =
332                                    journalStructurePersistence.findByStructureId(structureId);
333    
334                            if (structures.size() == 0) {
335                                    throw new NoSuchStructureException(
336                                            "No JournalStructure exists with the structure id " +
337                                                    structureId);
338                            }
339                            else {
340                                    return structures.get(0);
341                            }
342                    }
343                    else {
344                            return journalStructurePersistence.findByG_S(groupId, structureId);
345                    }
346            }
347    
348            public List<JournalStructure> getStructures() throws SystemException {
349                    return journalStructurePersistence.findAll();
350            }
351    
352            public List<JournalStructure> getStructures(long groupId)
353                    throws SystemException {
354    
355                    return journalStructurePersistence.findByGroupId(groupId);
356            }
357    
358            public List<JournalStructure> getStructures(
359                            long groupId, int start, int end)
360                    throws SystemException {
361    
362                    return journalStructurePersistence.findByGroupId(groupId, start, end);
363            }
364    
365            public int getStructuresCount(long groupId) throws SystemException {
366                    return journalStructurePersistence.countByGroupId(groupId);
367            }
368    
369            public List<JournalStructure> search(
370                            long companyId, long groupId, String keywords, int start, int end,
371                            OrderByComparator obc)
372                    throws SystemException {
373    
374                    return journalStructureFinder.findByKeywords(
375                            companyId, groupId, keywords, start, end, obc);
376            }
377    
378            public List<JournalStructure> search(
379                            long companyId, long groupId, String structureId, String name,
380                            String description, boolean andOperator, int start, int end,
381                            OrderByComparator obc)
382                    throws SystemException {
383    
384                    return journalStructureFinder.findByC_G_S_N_D(
385                            companyId, groupId, structureId, name, description, andOperator,
386                            start, end, obc);
387            }
388    
389            public int searchCount(long companyId, long groupId, String keywords)
390                    throws SystemException {
391    
392                    return journalStructureFinder.countByKeywords(
393                            companyId, groupId, keywords);
394            }
395    
396            public int searchCount(
397                            long companyId, long groupId, String structureId, String name,
398                            String description, boolean andOperator)
399                    throws SystemException {
400    
401                    return journalStructureFinder.countByC_G_S_N_D(
402                            companyId, groupId, structureId, name, description, andOperator);
403            }
404    
405            public JournalStructure updateStructure(
406                            long groupId, String structureId, String parentStructureId,
407                            String name, String description, String xsd,
408                            ServiceContext serviceContext)
409                    throws PortalException, SystemException {
410    
411                    structureId = structureId.trim().toUpperCase();
412    
413                    try {
414                            xsd = JournalUtil.formatXML(xsd);
415                    }
416                    catch (Exception e) {
417                            throw new StructureXsdException();
418                    }
419    
420                    validateParentStructureId(groupId, structureId, parentStructureId);
421                    validate(groupId, parentStructureId, name, description, xsd);
422    
423                    JournalStructure structure = journalStructurePersistence.findByG_S(
424                            groupId, structureId);
425    
426                    structure.setModifiedDate(serviceContext.getModifiedDate(null));
427                    structure.setParentStructureId(parentStructureId);
428                    structure.setName(name);
429                    structure.setDescription(description);
430                    structure.setXsd(xsd);
431    
432                    journalStructurePersistence.update(structure, false);
433    
434                    // Expando
435    
436                    ExpandoBridge expandoBridge = structure.getExpandoBridge();
437    
438                    expandoBridge.setAttributes(serviceContext);
439    
440                    return structure;
441            }
442    
443            protected void appendParentStructureElements(
444                            long groupId, String parentStructureId, List<Element> elements)
445                    throws Exception {
446    
447                    if (Validator.isNull(parentStructureId)) {
448                            return;
449                    }
450    
451                    JournalStructure parentStructure =
452                            journalStructurePersistence.findByG_S(groupId, parentStructureId);
453    
454                    appendParentStructureElements(
455                            groupId, parentStructure.getParentStructureId(), elements);
456    
457                    Document document = SAXReaderUtil.read(parentStructure.getXsd());
458    
459                    Element rootElement = document.getRootElement();
460    
461                    elements.addAll(rootElement.elements());
462            }
463    
464            protected void validate(List<Element> elements, Set<String> elNames)
465                    throws PortalException {
466    
467                    for (Element element : elements) {
468                            if (element.getName().equals("meta-data")) {
469                                    continue;
470                            }
471    
472                            String elName = element.attributeValue("name", StringPool.BLANK);
473                            String elType = element.attributeValue("type", StringPool.BLANK);
474    
475                            if (Validator.isNull(elName) ||
476                                    elName.startsWith(JournalStructureConstants.RESERVED)) {
477    
478                                    throw new StructureXsdException();
479                            }
480                            else {
481                                    char[] c = elName.toCharArray();
482    
483                                    for (int i = 0; i < c.length; i++) {
484                                            if ((!Validator.isChar(c[i])) &&
485                                                    (!Validator.isDigit(c[i])) && (c[i] != CharPool.DASH) &&
486                                                    (c[i] != CharPool.UNDERLINE)) {
487    
488                                                    throw new StructureXsdException();
489                                            }
490                                    }
491    
492                                    String completePath = elName;
493    
494                                    Element parentElement = element.getParent();
495    
496                                    while (!parentElement.isRootElement()) {
497                                            completePath =
498                                                    parentElement.attributeValue("name", StringPool.BLANK) +
499                                                            StringPool.SLASH + completePath;
500    
501                                            parentElement = parentElement.getParent();
502                                    }
503    
504                                    String elNameLowerCase = completePath.toLowerCase();
505    
506                                    if (elNames.contains(elNameLowerCase)) {
507                                            throw new DuplicateStructureElementException();
508                                    }
509                                    else {
510                                            elNames.add(elNameLowerCase);
511                                    }
512                            }
513    
514                            if (Validator.isNull(elType)) {
515                                    throw new StructureXsdException();
516                            }
517    
518                            validate(element.elements(), elNames);
519                    }
520            }
521    
522            protected void validate(
523                            long groupId, String structureId, boolean autoStructureId,
524                            String parentStructureId, String name, String description,
525                            String xsd)
526                    throws PortalException, SystemException {
527    
528                    if (!autoStructureId) {
529                            validateStructureId(structureId);
530    
531                            JournalStructure structure = journalStructurePersistence.fetchByG_S(
532                                    groupId, structureId);
533    
534                            if (structure != null) {
535                                    throw new DuplicateStructureIdException();
536                            }
537                    }
538    
539                    validateParentStructureId(groupId, structureId, parentStructureId);
540                    validate(groupId, parentStructureId, name, description, xsd);
541            }
542    
543            protected void validate(
544                            long groupId, String parentStructureId, String name,
545                            String description, String xsd)
546                    throws PortalException {
547    
548                    if (Validator.isNull(name)) {
549                            throw new StructureNameException();
550                    }
551                    else if (Validator.isNull(description)) {
552                            throw new StructureDescriptionException();
553                    }
554    
555                    if (Validator.isNull(xsd)) {
556                            throw new StructureXsdException();
557                    }
558                    else {
559                            try {
560                                    List<Element> elements = new ArrayList<Element>();
561    
562                                    appendParentStructureElements(
563                                            groupId, parentStructureId, elements);
564    
565                                    Document document = SAXReaderUtil.read(xsd);
566    
567                                    Element rootElement = document.getRootElement();
568    
569                                    if (rootElement.elements().isEmpty()) {
570                                            throw new StructureXsdException();
571                                    }
572    
573                                    elements.addAll(rootElement.elements());
574    
575                                    Set<String> elNames = new HashSet<String>();
576    
577                                    validate(elements, elNames);
578                            }
579                            catch (DuplicateStructureElementException dsee) {
580                                    throw dsee;
581                            }
582                            catch (StructureXsdException sxe) {
583                                    throw sxe;
584                            }
585                            catch (Exception e) {
586                                    throw new StructureXsdException();
587                            }
588                    }
589            }
590    
591            protected void validateParentStructureId(
592                            long groupId, String structureId, String parentStructureId)
593                    throws PortalException, SystemException {
594    
595                    if (Validator.isNull(parentStructureId)) {
596                            return;
597                    }
598    
599                    if (parentStructureId.equals(structureId)) {
600                            throw new StructureInheritanceException();
601                    }
602    
603                    JournalStructure parentStructure =
604                            journalStructurePersistence.fetchByG_S(groupId, parentStructureId);
605    
606                    while (parentStructure != null) {
607                            if ((parentStructure != null) &&
608                                    (parentStructure.getStructureId().equals(structureId)) ||
609                                    (parentStructure.getParentStructureId().equals(
610                                            structureId))) {
611    
612                                    throw new StructureInheritanceException();
613                            }
614    
615                            parentStructure = journalStructurePersistence.fetchByG_S(
616                                    groupId, parentStructure.getParentStructureId());
617                    }
618            }
619    
620            protected void validateStructureId(String structureId)
621                    throws PortalException {
622    
623                    if ((Validator.isNull(structureId)) ||
624                            (Validator.isNumber(structureId)) ||
625                            (structureId.indexOf(CharPool.SPACE) != -1)) {
626    
627                            throw new StructureIdException();
628                    }
629            }
630    
631            private static Log _log = LogFactoryUtil.getLog(
632                    JournalStructureLocalServiceImpl.class);
633    
634    }