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