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.plugins.explorer.resources.jcr;
017
018import java.util.List;
019
020import javax.jcr.Node;
021import javax.jcr.Property;
022import javax.jcr.RepositoryException;
023
024import org.ametys.plugins.explorer.ExplorerNode;
025import org.ametys.plugins.explorer.resources.ModifiableResourceCollection;
026import org.ametys.plugins.explorer.resources.Resource;
027import org.ametys.plugins.repository.AmetysObject;
028import org.ametys.plugins.repository.AmetysObjectIterable;
029import org.ametys.plugins.repository.AmetysRepositoryException;
030import org.ametys.plugins.repository.CopiableAmetysObject;
031import org.ametys.plugins.repository.ModifiableTraversableAmetysObject;
032import org.ametys.plugins.repository.UnknownAmetysObjectException;
033import org.ametys.plugins.repository.data.ametysobject.ModifiableModelLessDataAwareAmetysObject;
034import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder;
035import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelLessDataHolder;
036import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData;
037import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData;
038import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject;
039import org.ametys.plugins.repository.jcr.JCRTraversableAmetysObject;
040import org.ametys.plugins.repository.jcr.NameHelper;
041import org.ametys.plugins.repository.jcr.NameHelper.NameComputationMode;
042import org.ametys.plugins.repository.jcr.NodeHelper;
043import org.ametys.plugins.repository.jcr.NodeTypeHelper;
044import org.ametys.plugins.repository.trash.TrashElement;
045import org.ametys.plugins.repository.trash.TrashableAmetysObject;
046import org.ametys.plugins.repository.trash.UnknownParentException;
047
048/**
049 * {@link ExplorerNode} representing a collection of resources.
050 * @param <F> the actual type of factory.
051 */
052public class JCRResourcesCollection<F extends JCRResourcesCollectionFactory> extends DefaultTraversableAmetysObject<F> implements ModifiableResourceCollection, CopiableAmetysObject, ModifiableModelLessDataAwareAmetysObject, TrashableAmetysObject
053{
054    /** application id for resources collections. */
055    public static final String APPLICATION_ID = "Ametys.plugins.explorer.applications.resources.Resources";
056    
057    /** Constants for description metadata */
058    protected static final String DATA_DESCRIPTION = "description";
059    
060    /**
061     * Constructor
062     * @param node The jcr node
063     * @param parentPath The parent path
064     * @param factory The factory
065     */
066    public JCRResourcesCollection(Node node, String parentPath, F factory)
067    {
068        super(node, parentPath, factory);
069    }
070
071    @Override
072    public String getIconCls()
073    {
074        return "ametysicon-folder249";
075    }
076    
077    @Override
078    public String getApplicationId()
079    {
080        return APPLICATION_ID;
081    }
082    
083    @Override
084    public String getCollectionType()
085    {
086        return JCRResourcesCollectionFactory.RESOURCESCOLLECTION_NODETYPE;
087    }
088    
089    @Override
090    public String getResourceType()
091    {
092        return JCRResourceFactory.RESOURCES_NODETYPE;
093    }
094    
095    @Override
096    public String getResourcePath() throws AmetysRepositoryException
097    {
098        return getExplorerPath();
099    }
100
101    @Override
102    public String getExplorerPath()
103    {
104        AmetysObject parent = getParent();
105        
106        if (parent instanceof ExplorerNode)
107        {
108            return ((ExplorerNode) parent).getExplorerPath() + "/" + getName();
109        }
110        else
111        {
112            return "";
113        }
114    }
115    
116    public boolean hasChildResources() throws AmetysRepositoryException
117    {
118        AmetysObjectIterable<AmetysObject> children = getChildren();
119        for (AmetysObject child : children)
120        {
121            if (child instanceof Resource)
122            {
123                return true;
124            }
125        }
126
127        return false;
128    }
129    
130    public boolean hasChildExplorerNodes() throws AmetysRepositoryException
131    {
132        AmetysObjectIterable<AmetysObject> children = getChildren();
133        for (AmetysObject child : children)
134        {
135            if (child instanceof ExplorerNode)
136            {
137                return true;
138            }
139        }
140
141        return false;
142    }
143    
144    @Override
145    public AmetysObject copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException
146    {
147        try
148        {
149            String nodeTypeName = NodeTypeHelper.getNodeTypeName(getNode());
150            
151            JCRResourcesCollection copiedCollection = parent.createChild(name, nodeTypeName);
152            parent.saveChanges();
153            
154            for (AmetysObject object : getChildren())
155            {
156                if (object instanceof CopiableAmetysObject)
157                {
158                    ((CopiableAmetysObject) object).copyTo(copiedCollection, object.getName());
159                }
160            }
161            
162            return copiedCollection;
163        }
164        catch (RepositoryException e)
165        {
166            throw new AmetysRepositoryException("Error copying the collection " + getId() + " into " + parent.getId(), e);
167        }
168    }
169    
170    @Override
171    public AmetysObject copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException
172    {
173        return copyTo(parent, name);
174    }
175
176    @Override
177    public String getDescription()
178    {
179        return getValue(DATA_DESCRIPTION, null);
180    }
181
182    @Override
183    public void setDescription(String description)
184    {
185        setValue(DATA_DESCRIPTION, description);
186    }
187    
188    public ModifiableModelLessDataHolder getDataHolder()
189    {
190        ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode());
191        return new DefaultModifiableModelLessDataHolder(_getFactory().getDataTypesExtensionPoint(), repositoryData);
192    }
193    
194    public TrashElement moveToTrash()
195    {
196        TrashElement trashElement = _getFactory()._getTrashElementDAO().createTrashElement(this, getName());
197        // Clone the ametys object from the original session to trash session
198        Node storedNode = NodeHelper.cloneNode(getNode(), trashElement.getNode());
199        
200        try
201        {
202            storedNode.setProperty("ametys-internal:path", this.getParentPath());
203        }
204        catch (RepositoryException e)
205        {
206            throw new AmetysRepositoryException("failed to store the content path", e);
207        }
208
209        // Remove the node from the original session
210        remove();
211        
212        return trashElement;
213    }
214    
215    public JCRResourcesCollection restoreFromTrash() throws UnknownParentException
216    {
217        try
218        {
219            Property property = getNode().getProperty("ametys-internal:path");
220            String parentPath = property.getValue().getString();
221            property.remove();
222            JCRTraversableAmetysObject parent;
223            try
224            {
225                parent = _getFactory()._getResolver().resolveByPath(parentPath);
226            }
227            catch (UnknownAmetysObjectException e)
228            {
229                throw new UnknownParentException("No parent available at path " + parentPath, e);
230            }
231            
232            // Get the node name, can be adjust if another content has already the same node name
233            String nodeName = NameHelper.getUniqueAmetysObjectName(parent, getName(), NameComputationMode.USER_FRIENDLY, true);
234            
235            // Clone the ametys object from the trash session to default session
236            NodeHelper.cloneNode(getNode(), parent.getNode(), nodeName);
237            
238            // Remove the node from the trash session
239            remove();
240            
241            return parent.getChild(nodeName);
242        }
243        catch (RepositoryException e)
244        {
245            throw new AmetysRepositoryException("failed to store the content path", e);
246        }
247    }
248}