001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.LayoutFriendlyURLException;
018    import com.liferay.portal.LayoutHiddenException;
019    import com.liferay.portal.LayoutNameException;
020    import com.liferay.portal.LayoutParentLayoutIdException;
021    import com.liferay.portal.LayoutTypeException;
022    import com.liferay.portal.NoSuchLayoutException;
023    import com.liferay.portal.kernel.bean.BeanReference;
024    import com.liferay.portal.kernel.bean.IdentifiableBean;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.exception.SystemException;
027    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
028    import com.liferay.portal.kernel.util.LocaleUtil;
029    import com.liferay.portal.kernel.util.StringPool;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.model.Group;
032    import com.liferay.portal.model.Layout;
033    import com.liferay.portal.model.LayoutConstants;
034    import com.liferay.portal.model.LayoutSet;
035    import com.liferay.portal.model.LayoutSetPrototype;
036    import com.liferay.portal.model.impl.LayoutImpl;
037    import com.liferay.portal.service.persistence.LayoutPersistence;
038    import com.liferay.portal.service.persistence.LayoutSetPersistence;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portal.util.comparator.LayoutPriorityComparator;
041    import com.liferay.portlet.sites.util.SitesUtil;
042    
043    import java.util.List;
044    
045    /**
046     * @author Raymond Aug??
047     */
048    public class LayoutLocalServiceHelper implements IdentifiableBean {
049    
050            @Override
051            public String getBeanIdentifier() {
052                    return _beanIdentifier;
053            }
054    
055            public String getFriendlyURL(
056                            long groupId, boolean privateLayout, long layoutId, String name,
057                            String friendlyURL)
058                    throws PortalException, SystemException {
059    
060                    friendlyURL = getFriendlyURL(friendlyURL);
061    
062                    if (Validator.isNotNull(friendlyURL)) {
063                            return friendlyURL;
064                    }
065    
066                    friendlyURL = StringPool.SLASH + getFriendlyURL(name);
067    
068                    String originalFriendlyURL = friendlyURL;
069    
070                    for (int i = 1;; i++) {
071                            try {
072                                    validateFriendlyURL(
073                                            groupId, privateLayout, layoutId, friendlyURL);
074    
075                                    break;
076                            }
077                            catch (LayoutFriendlyURLException lfurle) {
078                                    int type = lfurle.getType();
079    
080                                    if (type == LayoutFriendlyURLException.DUPLICATE) {
081                                            friendlyURL = originalFriendlyURL + i;
082                                    }
083                                    else {
084                                            friendlyURL = StringPool.SLASH + layoutId;
085    
086                                            break;
087                                    }
088                            }
089                    }
090    
091                    return friendlyURL;
092            }
093    
094            public String getFriendlyURL(String friendlyURL) {
095                    return FriendlyURLNormalizerUtil.normalize(friendlyURL);
096            }
097    
098            public int getNextPriority(
099                            long groupId, boolean privateLayout, long parentLayoutId,
100                            String sourcePrototypeLayoutUuid, int defaultPriority)
101                    throws SystemException {
102    
103                    try {
104                            int priority = defaultPriority;
105    
106                            if (priority < 0) {
107                                    Layout layout = layoutPersistence.findByG_P_P_First(
108                                            groupId, privateLayout, parentLayoutId,
109                                            new LayoutPriorityComparator(false));
110    
111                                    priority = layout.getPriority() + 1;
112                            }
113    
114                            if ((priority < _PRIORITY_BUFFER) &&
115                                    Validator.isNull(sourcePrototypeLayoutUuid)) {
116    
117                                    LayoutSet layoutSet = layoutSetPersistence.fetchByG_P(
118                                            groupId, privateLayout);
119    
120                                    if (Validator.isNotNull(
121                                                    layoutSet.getLayoutSetPrototypeUuid())) {
122    
123                                            priority = priority + _PRIORITY_BUFFER;
124                                    }
125                            }
126    
127                            return priority;
128                    }
129                    catch (NoSuchLayoutException nsle) {
130                            return 0;
131                    }
132            }
133    
134            public long getParentLayoutId(
135                            long groupId, boolean privateLayout, long parentLayoutId)
136                    throws SystemException {
137    
138                    if (parentLayoutId != LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
139    
140                            // Ensure parent layout exists
141    
142                            Layout parentLayout = layoutPersistence.fetchByG_P_L(
143                                    groupId, privateLayout, parentLayoutId);
144    
145                            if (parentLayout == null) {
146                                    parentLayoutId = LayoutConstants.DEFAULT_PARENT_LAYOUT_ID;
147                            }
148                    }
149    
150                    return parentLayoutId;
151            }
152    
153            public boolean hasLayoutSetPrototypeLayout(
154                            LayoutSetPrototype layoutSetPrototype, String layoutUuid)
155                    throws PortalException, SystemException {
156    
157                    Group group = layoutSetPrototype.getGroup();
158    
159                    Layout layout = layoutPersistence.fetchByUUID_G_P(
160                            layoutUuid, group.getGroupId(), true);
161    
162                    if (layout != null) {
163                            return true;
164                    }
165    
166                    return false;
167            }
168    
169            @Override
170            public void setBeanIdentifier(String beanIdentifier) {
171                    _beanIdentifier = beanIdentifier;
172            }
173    
174            public void validate(
175                            long groupId, boolean privateLayout, long layoutId,
176                            long parentLayoutId, String name, String type, boolean hidden,
177                            String friendlyURL)
178                    throws PortalException, SystemException {
179    
180                    validateName(name);
181    
182                    boolean firstLayout = false;
183    
184                    if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
185                            List<Layout> layouts = layoutPersistence.findByG_P_P(
186                                    groupId, privateLayout, parentLayoutId, 0, 1);
187    
188                            if (layouts.size() == 0) {
189                                    firstLayout = true;
190                            }
191                            else {
192                                    long firstLayoutId = layouts.get(0).getLayoutId();
193    
194                                    if (firstLayoutId == layoutId) {
195                                            firstLayout = true;
196                                    }
197                            }
198                    }
199    
200                    if (firstLayout) {
201                            validateFirstLayout(type);
202                    }
203    
204                    if (!PortalUtil.isLayoutParentable(type)) {
205                            if (layoutPersistence.countByG_P_P(
206                                            groupId, privateLayout, layoutId) > 0) {
207    
208                                    throw new LayoutTypeException(
209                                            LayoutTypeException.NOT_PARENTABLE);
210                            }
211                    }
212    
213                    validateFriendlyURL(groupId, privateLayout, layoutId, friendlyURL);
214            }
215    
216            public void validateFirstLayout(String type) throws PortalException {
217                    if (Validator.isNull(type) || !PortalUtil.isLayoutFirstPageable(type)) {
218                            LayoutTypeException lte = new LayoutTypeException(
219                                    LayoutTypeException.FIRST_LAYOUT);
220    
221                            lte.setLayoutType(type);
222    
223                            throw lte;
224                    }
225            }
226    
227            public void validateFriendlyURL(
228                            long groupId, boolean privateLayout, long layoutId,
229                            String friendlyURL)
230                    throws PortalException, SystemException {
231    
232                    if (Validator.isNull(friendlyURL)) {
233                            return;
234                    }
235    
236                    int exceptionType = LayoutImpl.validateFriendlyURL(friendlyURL);
237    
238                    if (exceptionType != -1) {
239                            throw new LayoutFriendlyURLException(exceptionType);
240                    }
241    
242                    Layout layout = layoutPersistence.fetchByG_P_F(
243                            groupId, privateLayout, friendlyURL);
244    
245                    if ((layout != null) && (layout.getLayoutId() != layoutId)) {
246                            throw new LayoutFriendlyURLException(
247                                    LayoutFriendlyURLException.DUPLICATE);
248                    }
249    
250                    LayoutImpl.validateFriendlyURLKeyword(friendlyURL);
251    
252                    /*List<FriendlyURLMapper> friendlyURLMappers =
253                            portletLocalService.getFriendlyURLMappers();
254    
255                    for (FriendlyURLMapper friendlyURLMapper : friendlyURLMappers) {
256                            if (friendlyURL.indexOf(friendlyURLMapper.getMapping()) != -1) {
257                                    LayoutFriendlyURLException lfurle =
258                                            new LayoutFriendlyURLException(
259                                                    LayoutFriendlyURLException.KEYWORD_CONFLICT);
260    
261                                    lfurle.setKeywordConflict(friendlyURLMapper.getMapping());
262    
263                                    throw lfurle;
264                            }
265                    }*/
266    
267                    String layoutIdFriendlyURL = friendlyURL.substring(1);
268    
269                    if (Validator.isNumber(layoutIdFriendlyURL) &&
270                            !layoutIdFriendlyURL.equals(String.valueOf(layoutId))) {
271    
272                            LayoutFriendlyURLException lfurle = new LayoutFriendlyURLException(
273                                    LayoutFriendlyURLException.POSSIBLE_DUPLICATE);
274    
275                            lfurle.setKeywordConflict(layoutIdFriendlyURL);
276    
277                            throw lfurle;
278                    }
279            }
280    
281            public void validateName(String name) throws PortalException {
282                    if (Validator.isNull(name)) {
283                            throw new LayoutNameException();
284                    }
285            }
286    
287            public void validateName(String name, String languageId)
288                    throws PortalException {
289    
290                    String defaultLanguageId = LocaleUtil.toLanguageId(
291                            LocaleUtil.getDefault());
292    
293                    if (defaultLanguageId.equals(languageId)) {
294                            validateName(name);
295                    }
296            }
297    
298            public void validateParentLayoutId(
299                            long groupId, boolean privateLayout, long layoutId,
300                            long parentLayoutId)
301                    throws PortalException, SystemException {
302    
303                    Layout layout = layoutPersistence.findByG_P_L(
304                            groupId, privateLayout, layoutId);
305    
306                    if (parentLayoutId != layout.getParentLayoutId()) {
307    
308                            // Layouts can always be moved to the root level
309    
310                            if (parentLayoutId == LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
311                                    return;
312                            }
313    
314                            // Layout cannot become a child of a layout that is not parentable
315    
316                            Layout parentLayout = layoutPersistence.findByG_P_L(
317                                    groupId, privateLayout, parentLayoutId);
318    
319                            if (!PortalUtil.isLayoutParentable(parentLayout)) {
320                                    throw new LayoutParentLayoutIdException(
321                                            LayoutParentLayoutIdException.NOT_PARENTABLE);
322                            }
323    
324                            // Layout cannot become a child of a layout that is not sortable
325                            // because it is linked to a layout set prototype
326    
327                            if (!SitesUtil.isLayoutSortable(parentLayout)) {
328                                    throw new LayoutParentLayoutIdException(
329                                            LayoutParentLayoutIdException.NOT_SORTABLE);
330                            }
331    
332                            // Layout cannot become descendant of itself
333    
334                            if (PortalUtil.isLayoutDescendant(layout, parentLayoutId)) {
335                                    throw new LayoutParentLayoutIdException(
336                                            LayoutParentLayoutIdException.SELF_DESCENDANT);
337                            }
338    
339                            // If layout is moved, the new first layout must be valid
340    
341                            if (layout.getParentLayoutId() ==
342                                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID) {
343    
344                                    List<Layout> layouts = layoutPersistence.findByG_P_P(
345                                            groupId, privateLayout,
346                                            LayoutConstants.DEFAULT_PARENT_LAYOUT_ID, 0, 2);
347    
348                                    // You can only reach this point if there are more than two
349                                    // layouts at the root level because of the descendant check
350    
351                                    long firstLayoutId = layouts.get(0).getLayoutId();
352    
353                                    if (firstLayoutId == layoutId) {
354                                            Layout secondLayout = layouts.get(1);
355    
356                                            try {
357                                                    validateFirstLayout(secondLayout.getType());
358                                            }
359                                            catch (LayoutHiddenException lhe) {
360                                                    throw new LayoutParentLayoutIdException(
361                                                            LayoutParentLayoutIdException.FIRST_LAYOUT_HIDDEN);
362                                            }
363                                            catch (LayoutTypeException lte) {
364                                                    throw new LayoutParentLayoutIdException(
365                                                            LayoutParentLayoutIdException.FIRST_LAYOUT_TYPE);
366                                            }
367                                    }
368                            }
369                    }
370            }
371    
372            @BeanReference(type = LayoutPersistence.class)
373            protected LayoutPersistence layoutPersistence;
374    
375            @BeanReference(type = LayoutSetPersistence.class)
376            protected LayoutSetPersistence layoutSetPersistence;
377    
378            private static final int _PRIORITY_BUFFER = 1000000;
379    
380            private String _beanIdentifier;
381    
382    }