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