001/*
002 *  Copyright 2011 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016
017package org.ametys.web.repository.dom;
018
019import java.util.Iterator;
020
021import org.w3c.dom.Element;
022import org.w3c.dom.Node;
023
024import org.ametys.cms.tag.TagProviderExtensionPoint;
025import org.ametys.core.right.RightManager;
026import org.ametys.core.user.UserIdentity;
027import org.ametys.plugins.repository.AmetysObjectIterable;
028import org.ametys.plugins.repository.EmptyIterable;
029import org.ametys.plugins.repository.dom.AmetysObjectElement;
030import org.ametys.web.pageaccess.RestrictedPagePolicy;
031import org.ametys.web.renderingcontext.RenderingContext;
032import org.ametys.web.renderingcontext.RenderingContextHandler;
033import org.ametys.web.repository.page.Page;
034import org.ametys.web.repository.page.PagesContainer;
035
036/**
037 * DOM {@link Element} wrapping a {@link PagesContainer}.
038 * @param <A> the actual type of the wrapped {@link PagesContainer}.
039 */
040public abstract class AbstractPagesContainerElement<A extends PagesContainer> extends AmetysObjectElement<A>
041{
042    /** Prefix for sitemap namespace. */
043    public static final String NAMESPACE_PREFIX = "sitemap";
044    /** URI for sitemap namespace. */
045    public static final String NAMESPACE_URI = "http://www.ametys.org/inputdata/sitemap/3.0";
046
047    /** The right manager */
048    protected RightManager _rightManager;
049    /** The rendering context handler. */
050    protected RenderingContextHandler _renderingContextHandler;
051    /** The path of the wrapped page. */
052    protected String _currentPagePath;
053    /** The identity of the current user. */
054    protected UserIdentity _userIdentity;
055    /** the {@link RestrictedPagePolicy} of the current site. */
056    protected RestrictedPagePolicy _policy;
057    /** should child pages displays invisible page */
058    protected boolean _includeInvisiblePages;
059    /** The depth  of childs to display */
060    protected long _depth;
061    /** The tag provider extension point */
062    protected TagProviderExtensionPoint _tagProviderExtensionPoint;
063    
064    private AmetysObjectIterable<? extends Page> _children;
065    
066    /**
067     * Constructor.
068     * @param pagesContainer the wrapped {@link PagesContainer}.
069     * @param rightManager the right manager
070     * @param currentPagePath the path of the current page, or null if none.
071     * @param renderingContextHandler the {@link RenderingContextHandler}.
072     * @param userIdentity the identity of the current user, or null if none.
073     * @param depth The depth to get. 1 for root pages, 0 for this node only, -1 for infinite.
074     * @param includeInvisiblePages Should return child invisible pages
075     * @param tagProviderExtensionPoint the tag provider extension point
076     */
077    public AbstractPagesContainerElement(A pagesContainer, RightManager rightManager, RenderingContextHandler renderingContextHandler, String currentPagePath, UserIdentity userIdentity, long depth, boolean includeInvisiblePages, TagProviderExtensionPoint tagProviderExtensionPoint)
078    {
079        this(pagesContainer, null, rightManager, renderingContextHandler, currentPagePath, userIdentity, depth, includeInvisiblePages, tagProviderExtensionPoint);
080    }
081    
082    /**
083     * Constructor.
084     * @param pagesContainer the wrapped {@link PagesContainer}.
085     * @param parent the parent container.
086     * @param rightManager the right manager
087     * @param currentPagePath the path of the current page, or null if none.
088     * @param renderingContextHandler the {@link RenderingContextHandler}.
089     * @param userIdentity the identity of the current user, or null if none.
090     * @param depth The depth to get. 1 for root pages, 0 for this node only, -1 for infinite.
091     * @param includeInvisiblePages Should return child invisible pages
092     * @param tagProviderExtensionPoint the tag provider extension point
093     */
094    public AbstractPagesContainerElement(A pagesContainer, AbstractPagesContainerElement<PagesContainer> parent, RightManager rightManager, RenderingContextHandler renderingContextHandler, String currentPagePath, UserIdentity userIdentity, long depth, boolean includeInvisiblePages, TagProviderExtensionPoint tagProviderExtensionPoint)
095    {
096        super(pagesContainer, parent);
097        _rightManager = rightManager;
098        _renderingContextHandler = renderingContextHandler;
099        _currentPagePath = currentPagePath;
100        _userIdentity = userIdentity;
101        _policy = _object.getSite().getRestrictedPagePolicy();
102        _includeInvisiblePages = includeInvisiblePages;
103        _depth = depth;
104        _tagProviderExtensionPoint = tagProviderExtensionPoint;
105    }
106    
107    @Override
108    public String getNamespaceURI()
109    {
110        //return "http://www.ametys.org/inputdata/sitemap/3.0";
111        return null;
112    }
113    
114    AmetysObjectIterable<? extends Page> getChildren()
115    {
116        if (_depth == 0)
117        {
118            _children = new EmptyIterable<>();
119        }
120        else if (_children == null)
121        {
122            _children = _object.getChildrenPages(_includeInvisiblePages);
123        }
124        
125        return _children;
126    }
127    
128    @Override
129    public boolean hasChildNodes()
130    {
131        if (_depth == 0)
132        {
133            _children = new EmptyIterable<>();
134        }
135        else if (_children == null)
136        {
137            _children = _object.getChildrenPages(_includeInvisiblePages);
138        }
139        
140        return _children.iterator().hasNext();
141    }
142    
143    @SuppressWarnings("unchecked")
144    @Override
145    public Node getFirstChild()
146    {
147        if (_depth == 0)
148        {
149            _children = new EmptyIterable<>();
150        }
151        else if (_children == null)
152        {
153            _children = _object.getChildrenPages(_includeInvisiblePages);
154        }
155        
156        Iterator<? extends Page> it = _children.iterator();
157        
158        if (!it.hasNext())
159        {
160            return null;
161        }
162        
163        RenderingContext renderingContext = _renderingContextHandler.getRenderingContext();
164        boolean inBackOffice = renderingContext == RenderingContext.BACK || renderingContext == RenderingContext.PREVIEW;
165        
166        Page child = null;
167        
168        while (child == null && it.hasNext())
169        {
170            Page page = it.next();
171            if (inBackOffice || _policy == RestrictedPagePolicy.DISPLAYED || _rightManager.hasReadAccess(_userIdentity, page))
172            {
173                child = page;
174            }
175        }
176        
177        return child == null ? null : new PageElement(child, (AbstractPagesContainerElement<PagesContainer>) this, _rightManager, _renderingContextHandler, _currentPagePath, _userIdentity, Math.max(_depth - 1, -1), _includeInvisiblePages, _tagProviderExtensionPoint);
178    }
179    
180    @SuppressWarnings("unchecked")
181    @Override
182    public Node getNextSibling()
183    {
184        if (_parent == null)
185        {
186            return null;
187        }
188        
189        AmetysObjectIterable<? extends Page> children = ((AbstractPagesContainerElement<PagesContainer>) _parent).getChildren();
190        
191        RenderingContext renderingContext = _renderingContextHandler.getRenderingContext();
192        boolean inBackOffice = renderingContext == RenderingContext.BACK || renderingContext == RenderingContext.PREVIEW;
193        
194        boolean isNext = false;
195        Page nextSibling = null;
196        Iterator<? extends Page> it = children.iterator();
197        
198        while (nextSibling == null && it.hasNext())
199        {
200            Page child = it.next();
201            
202            if (isNext && (inBackOffice || _policy == RestrictedPagePolicy.DISPLAYED || _rightManager.hasReadAccess(_userIdentity, child)))
203            {
204                nextSibling = child;
205            }
206            else if (_object.getId().equals(child.getId()))
207            {
208                isNext = true;
209            }
210        }
211        
212        return nextSibling == null ? null : new PageElement(nextSibling, (AbstractPagesContainerElement<PagesContainer>) _parent, _rightManager, _renderingContextHandler, _currentPagePath, _userIdentity, _depth, _includeInvisiblePages, _tagProviderExtensionPoint);
213    }
214}