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.cmis;
017
018import java.util.ArrayList;
019import java.util.Collection;
020
021import org.apache.chemistry.opencmis.client.api.CmisObject;
022import org.apache.chemistry.opencmis.client.api.Document;
023import org.apache.chemistry.opencmis.client.api.Folder;
024import org.apache.chemistry.opencmis.client.api.ItemIterable;
025import org.apache.chemistry.opencmis.client.api.Session;
026import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
027import org.apache.commons.lang.StringUtils;
028
029import org.ametys.plugins.explorer.ExplorerNode;
030import org.ametys.plugins.explorer.resources.ResourceCollection;
031import org.ametys.plugins.repository.AmetysObject;
032import org.ametys.plugins.repository.AmetysRepositoryException;
033import org.ametys.plugins.repository.CollectionIterable;
034import org.ametys.plugins.repository.UnknownAmetysObjectException;
035
036/**
037 * Implementation of an {@link ExplorerNode}, backed by a CMIS server.<br>
038 */
039public class CMISResourcesCollection implements ResourceCollection
040{
041    /** Application id for resources collections. */
042    public static final String APPLICATION_ID = "Ametys.plugins.explorer.applications.resources.Resources";
043
044    private final Folder _cmisFolder;
045    private final CMISRootResourcesCollection _root;
046    private AmetysObject _parent;
047    
048    /**
049     * Creates a {@link CMISResourcesCollection} 
050     * @param folder The CMIS folder
051     * @param root The root of the virtual tree
052     * @param parent the parent {@link AmetysObject} if known
053     */
054    public CMISResourcesCollection(Folder folder, CMISRootResourcesCollection root, AmetysObject parent)
055    {
056        _cmisFolder = folder;
057        _root = root;
058        _parent = parent;
059    }
060    
061    @Override
062    public String getApplicationId()
063    {
064        return APPLICATION_ID;
065    }
066
067    @Override
068    public String getIconCls()
069    {
070        return "folder";
071    }
072
073    @Override
074    public String getId() throws AmetysRepositoryException
075    {
076        return getCmisRoot().getId() + "/" + getCmisFolder().getId();
077    }
078
079    @Override
080    public String getName() throws AmetysRepositoryException
081    {
082        return getCmisFolder().getName();
083    }
084    
085    /**
086     * Retrieves the {@link CMISRootResourcesCollection}
087     * @return the {@link CMISRootResourcesCollection}
088     */
089    public CMISRootResourcesCollection getCmisRoot ()
090    {
091        return _root;
092    }
093    
094    /**
095     * Retrieves the {@link Folder}
096     * @return the {@link Folder}
097     */
098    public Folder getCmisFolder ()
099    {
100        return _cmisFolder;
101    }
102
103    @SuppressWarnings("unchecked")
104    @Override
105    public AmetysObject getParent() throws AmetysRepositoryException
106    {
107        if (_parent != null)
108        {
109            return _parent;
110        }
111        
112        Session session = getCmisRoot().getSession();
113        if (session == null)
114        {
115            throw new UnknownAmetysObjectException("Failed to connect to CMIS server");
116        }
117        
118        String parentId = _cmisFolder.getParentId();
119        Folder parent = (Folder) session.getObject(parentId);
120        
121        if (parent.isRootFolder())
122        {
123            _parent = getCmisRoot();
124            return _parent;
125        }
126        else
127        {
128            _parent = new CMISResourcesCollection(parent, _root, null);
129            return _parent;
130        }
131    }
132
133    @Override
134    public String getParentPath() throws AmetysRepositoryException
135    {
136        return getParent().getPath();
137    }
138
139    @Override
140    public String getPath() throws AmetysRepositoryException
141    {
142        return getParentPath() + "/" + getName();
143    }
144    
145    @Override
146    @SuppressWarnings("unchecked")
147    public AmetysObject getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException
148    {
149        Session session = getCmisRoot().getSession();
150        if (session == null)
151        {
152            throw new UnknownAmetysObjectException("Failed to connect to CMIS server");
153        }
154        
155        CmisObject child = session.getObjectByPath(path);
156        BaseTypeId baseTypeId = child.getBaseType().getBaseTypeId(); 
157        
158        if (baseTypeId.equals(BaseTypeId.CMIS_FOLDER))
159        {
160            return new CMISResourcesCollection((Folder) child, _root, this);            
161        }
162        if (baseTypeId.equals(BaseTypeId.CMIS_DOCUMENT))
163        {
164            Document cmisDoc = (Document) child;
165            // Check if CMIS document has content, if not ignore it
166            if (cmisDoc.getContentStream() != null)
167            {
168                return new CMISResource((Document) child, _root, this);  
169            }
170            throw new UnknownAmetysObjectException("The CMIS document " + path + " has no content");   
171        }
172        else
173        {
174            throw new IllegalArgumentException("Unhandled CMIS type: " + baseTypeId);
175        }
176    }
177
178    
179    @Override
180    public CollectionIterable<AmetysObject> getChildren() throws AmetysRepositoryException
181    {
182        Collection<AmetysObject> aoChildren = new ArrayList<>();
183        
184        ItemIterable<CmisObject> children = getCmisFolder().getChildren();
185        for (CmisObject child : children)
186        {
187            BaseTypeId baseTypeId = child.getBaseTypeId(); 
188            if (baseTypeId.equals(BaseTypeId.CMIS_FOLDER))
189            {
190                aoChildren.add(new CMISResourcesCollection((Folder) child, _root, this));
191            }
192            else if (baseTypeId.equals(BaseTypeId.CMIS_DOCUMENT))
193            {
194                Document cmisDoc = (Document) child;
195                
196                // Check if CMIS document has content, if not ignore it
197                if (StringUtils.isNotEmpty(cmisDoc.getContentStreamFileName()))
198                {
199                    aoChildren.add(new CMISResource(cmisDoc, _root, this));
200                }
201            }
202            else
203            {
204                throw new IllegalArgumentException("Unhandled CMIS type: " + baseTypeId);
205            }
206        }
207
208        return new CollectionIterable<>(aoChildren);
209    }
210
211    @Override
212    public boolean hasChild(String name) throws AmetysRepositoryException
213    {
214        ItemIterable<CmisObject> children = _cmisFolder.getChildren();
215        for (CmisObject child : children)
216        {
217            if (child.getName().equals(name))
218            {
219                return true;
220            }
221        }
222        
223        return false;
224    }
225    
226    public boolean hasChildResources() throws AmetysRepositoryException
227    {
228        // we don't actually know if there are children or not, 
229        // but it's an optimization to don't make another CMIS request
230        return true;
231    }
232    
233    public boolean hasChildExplorerNodes() throws AmetysRepositoryException
234    {
235        // we don't actually know if there are children or not, 
236        // but it's an optimization to don't make another CMIS request
237        return true;
238    }
239    
240    @Override
241    public String getExplorerPath()
242    {
243        AmetysObject parent = getParent();
244        
245        if (parent instanceof ExplorerNode)
246        {
247            return ((ExplorerNode) parent).getExplorerPath() + "/" + getName();
248        }
249        else
250        {
251            return "";
252        }
253    }
254    
255    @Override
256    public String getResourcePath() throws AmetysRepositoryException
257    {
258        return getExplorerPath();
259    }
260    
261    @Override
262    public String getDescription()
263    {
264        return null;
265    }
266}