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                if (rootAttachments != null && rootAttachments instanceof JCRAmetysObject && cContent instanceof JCRAmetysObject)
088                {
089                    AmetysObjectIterable<AmetysObject> attachments = rootAttachments.getChildren();
090
091                    // As root attachments node is auto-created it can not be copied manually: copy the children of root attachments.
092                    ResourceCollection cRootAttachments = ((ModifiableWebContent) cContent).getRootAttachments();
093                    if (cRootAttachments != null) // root attachments can be missing if the content is an (unmodifiable) old version
094                    {
095                        Node cResourcesNode = ((JCRAmetysObject) cRootAttachments).getNode();
096                        
097                        for (AmetysObject attachment : attachments)
098                        {
099                            if (attachment instanceof JCRAmetysObject)
100                            {
101                                Node resourceNode = ((JCRAmetysObject) attachment).getNode();
102                                getNode().getSession().getWorkspace().copy(resourceNode.getPath(), cResourcesNode.getPath() + "/" + resourceNode.getName());
103                            }
104                        }
105                    }
106                }
107                
108                cContent.saveChanges();
109            }
110        }
111        catch (RepositoryException e)
112        {
113            throw new AmetysRepositoryException(e);
114        }
115        
116        return cContent;
117    }
118    
119    @Override
120    public Collection<Page> getReferencingPages()
121    {
122        ArrayList<Page> pages = new ArrayList<>();
123        try
124        {
125            PropertyIterator itReferences = getNode().getReferences();
126            
127            while (itReferences.hasNext())
128            {
129                Node refererNode = itReferences.nextProperty().getParent();
130                
131                if (NodeTypeHelper.isNodeType(refererNode, "ametys:zoneItem"))
132                {
133                    // /page/ametys-internal:zones/default/ametys-internal:zoneItems/ametys:zoneItem
134                    Node pageNode = refererNode.getParent().getParent().getParent().getParent();
135                    Page page = _getFactory().resolveAmetysObject(pageNode);
136                    pages.add(page);
137                }
138            }
139        }
140        catch (RepositoryException e)
141        {
142            throw new AmetysRepositoryException("Unable to resolve references for content " + getId(), e);
143        }
144        
145        return pages;
146    }
147    
148    @Override
149    public Collection<ZoneItem> getReferencingZoneItems()
150    {
151        ArrayList<ZoneItem> zoneItems = new ArrayList<>();
152        try
153        {
154            PropertyIterator itReferences = getNode().getReferences();
155            
156            while (itReferences.hasNext())
157            {
158                Node refererNode = itReferences.nextProperty().getParent();
159                
160                if (NodeTypeHelper.isNodeType(refererNode, "ametys:zoneItem"))
161                {
162                    ZoneItem zoneItem = _getFactory().resolveAmetysObject(refererNode);
163                    zoneItems.add(zoneItem);
164                }
165            }
166        }
167        catch (RepositoryException e)
168        {
169            throw new AmetysRepositoryException("Unable to resolve references for content " + getId(), e);
170        }
171        
172        return zoneItems;
173    }
174    
175    @Override
176    public ResourceCollection getRootAttachments() throws AmetysRepositoryException
177    {
178        ResourceCollection attachments = null;
179        
180        if (hasChild(ATTACHMENTS_NODE_NAME))
181        {
182            attachments = getChild(ATTACHMENTS_NODE_NAME);
183        }
184        
185        return attachments;
186    }
187    
188    @Override
189    public Site getSite()
190    {
191        return _getFactory().getSite(getSiteName());
192    }
193    
194    @Override
195    public String getSiteName()
196    {
197        // TODO CMS-9336 this metadata should be stored as internal using data holders
198        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
199        return repositoryData.getString(METADATA_SITE);
200    }
201    
202    @Override
203    public boolean hasChild(String name) throws AmetysRepositoryException
204    {
205        return _getFactory().hasChild(this, name);
206    }
207    
208    @SuppressWarnings("unchecked")
209    @Override
210    public <A extends AmetysObject> A createChild(String name, String type) throws AmetysRepositoryException, RepositoryIntegrityViolationException
211    {
212        return (A) _getFactory().createChild(this, name, type);
213    }
214    
215    @SuppressWarnings("unchecked")
216    @Override
217    public <A extends AmetysObject> A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
218    {
219        return (A) _getFactory().getChild(this, path);
220    }
221    
222    @Override
223    public <A extends AmetysObject> AmetysObjectIterable<A> getChildren() throws AmetysRepositoryException
224    {
225        return _getFactory().getChildren(this);
226    }
227    
228}