001/*
002 *  Copyright 2010 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 */
016package org.ametys.web.repository.content.jcr;
017
018import java.util.ArrayList;
019import java.util.Collection;
020import java.util.Set;
021
022import javax.jcr.Node;
023import javax.jcr.PropertyIterator;
024import javax.jcr.RepositoryException;
025
026import org.ametys.cms.repository.DefaultContent;
027import org.ametys.cms.repository.ModifiableContent;
028import org.ametys.plugins.explorer.resources.ResourceCollection;
029import org.ametys.plugins.repository.AmetysObject;
030import org.ametys.plugins.repository.AmetysObjectIterable;
031import org.ametys.plugins.repository.AmetysRepositoryException;
032import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
033import org.ametys.plugins.repository.RepositoryIntegrityViolationException;
034import org.ametys.plugins.repository.UnknownAmetysObjectException;
035import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
036import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
037import org.ametys.plugins.repository.jcr.JCRAmetysObject;
038import org.ametys.plugins.repository.jcr.NodeTypeHelper;
039import org.ametys.plugins.repository.tag.TagAwareAmetysObject;
040import org.ametys.web.repository.content.ModifiableWebContent;
041import org.ametys.web.repository.content.WebContent;
042import org.ametys.web.repository.page.Page;
043import org.ametys.web.repository.page.ZoneItem;
044import org.ametys.web.repository.site.Site;
045
046/**
047 * {@link DefaultContent} which is {@link TagAwareAmetysObject}.
048 * @param <F> the actual type of factory.
049 */
050public class DefaultWebContent<F extends DefaultWebContentFactory> extends DefaultContent<F> implements WebContent
051{
052    
053    /** Constants for site Metadata. */
054    public static final String METADATA_SITE = "site";
055    
056    /**
057     * Creates a {@link DefaultWebContent}.
058     * @param node the node backing this {@link DefaultWebContent}.
059     * @param parentPath the parent path in the Ametys hierarchy.
060     * @param factory the {@link DefaultWebContentFactory} which creates the AmetysObject.
061     */
062    public DefaultWebContent(Node node, String parentPath, F factory)
063    {
064        super(node, parentPath, factory);
065    }
066
067    @Override
068    public ModifiableContent copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
069    {
070        ModifiableContent cContent = super.copyTo(parent, name);
071        
072        try
073        {
074            if (cContent instanceof ModifiableWebContent)
075            {
076                ((ModifiableWebContent) cContent).setSiteName(getSiteName());
077                
078                // Copy tags
079                Set<String> tags = getTags();
080                for (String tag : tags)
081                {
082                    ((ModifiableWebContent) cContent).tag(tag);
083                }
084                
085                // Copy attachments
086                ResourceCollection rootAttachments = getRootAttachments();
087                
088                AmetysObjectIterable<AmetysObject> attachments = rootAttachments.getChildren();
089                
090                if (rootAttachments instanceof JCRAmetysObject && cContent instanceof JCRAmetysObject)
091                {
092                    // As root attachments node is auto-created it can not be copied manually : copy the children of root attachments.
093                    ResourceCollection cRootAttachments = ((ModifiableWebContent) cContent).getRootAttachments();
094                    Node cResourcesNode = ((JCRAmetysObject) cRootAttachments).getNode();
095                    
096                    for (AmetysObject attachment : attachments)
097                    {
098                        if (attachment instanceof JCRAmetysObject)
099                        {
100                            Node resourceNode = ((JCRAmetysObject) attachment).getNode();
101                            getNode().getSession().getWorkspace().copy(resourceNode.getPath(), cResourcesNode.getPath() + "/" + resourceNode.getName());
102                        }
103                    }
104                }
105                
106                cContent.saveChanges();
107            }
108        }
109        catch (RepositoryException e)
110        {
111            throw new AmetysRepositoryException(e);
112        }
113        
114        return cContent;
115    }
116    
117    @Override
118    public Collection<Page> getReferencingPages()
119    {
120        ArrayList<Page> pages = new ArrayList<>();
121        try
122        {
123            PropertyIterator itReferences = getNode().getReferences();
124            
125            while (itReferences.hasNext())
126            {
127                Node refererNode = itReferences.nextProperty().getParent();
128                
129                if (NodeTypeHelper.isNodeType(refererNode, "ametys:zoneItem"))
130                {
131                    // /page/ametys-internal:zones/default/ametys-internal:zoneItems/ametys:zoneItem
132                    Node pageNode = refererNode.getParent().getParent().getParent().getParent();
133                    Page page = _getFactory().resolveAmetysObject(pageNode);
134                    pages.add(page);
135                }
136            }
137        }
138        catch (RepositoryException e)
139        {
140            throw new AmetysRepositoryException("Unable to resolve references for content " + getId(), e);
141        }
142        
143        return pages;
144    }
145    
146    @Override
147    public Collection<ZoneItem> getReferencingZoneItems()
148    {
149        ArrayList<ZoneItem> zoneItems = new ArrayList<>();
150        try
151        {
152            PropertyIterator itReferences = getNode().getReferences();
153            
154            while (itReferences.hasNext())
155            {
156                Node refererNode = itReferences.nextProperty().getParent();
157                
158                if (NodeTypeHelper.isNodeType(refererNode, "ametys:zoneItem"))
159                {
160                    ZoneItem zoneItem = _getFactory().resolveAmetysObject(refererNode);
161                    zoneItems.add(zoneItem);
162                }
163            }
164        }
165        catch (RepositoryException e)
166        {
167            throw new AmetysRepositoryException("Unable to resolve references for content " + getId(), e);
168        }
169        
170        return zoneItems;
171    }
172    
173    @Override
174    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
175    {
176        ResourceCollection attachments = null;
177        
178        if (hasChild(ATTACHMENTS_NODE_NAME))
179        {
180            attachments = getChild(ATTACHMENTS_NODE_NAME);
181        }
182        
183        return attachments;
184    }
185    
186    @Override
187    public Site getSite()
188    {
189        return _getFactory().getSite(getSiteName());
190    }
191    
192    @Override
193    public String getSiteName()
194    {
195        // TODO CMS-9336 this metadata should be stored as internal using data holders
196        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
197        return repositoryData.getString(METADATA_SITE);
198    }
199    
200    @Override
201    public boolean hasChild(String name) throws AmetysRepositoryException
202    {
203        return _getFactory().hasChild(this, name);
204    }
205    
206    @SuppressWarnings("unchecked")
207    @Override
208    public <A extends AmetysObject> A createChild(String name, String type) throws AmetysRepositoryException, RepositoryIntegrityViolationException
209    {
210        return (A) _getFactory().createChild(this, name, type);
211    }
212    
213    @SuppressWarnings("unchecked")
214    @Override
215    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
216    {
217        return (A) _getFactory().getChild(this, path);
218    }
219    
220    @Override
221    public <A extends AmetysObject> AmetysObjectIterable<A> getChildren() throws AmetysRepositoryException
222    {
223        return _getFactory().getChildren(this);
224    }
225    
226}