001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
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 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.opencmis.impl.client;
020
021import java.util.ArrayList;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.chemistry.opencmis.client.api.CmisObject;
026import org.apache.chemistry.opencmis.client.api.Document;
027import org.apache.chemistry.opencmis.client.api.FileableCmisObject;
028import org.apache.chemistry.opencmis.client.api.Folder;
029import org.apache.chemistry.opencmis.client.api.FolderType;
030import org.apache.chemistry.opencmis.client.api.Item;
031import org.apache.chemistry.opencmis.client.api.ItemIterable;
032import org.apache.chemistry.opencmis.client.api.ObjectId;
033import org.apache.chemistry.opencmis.client.api.ObjectType;
034import org.apache.chemistry.opencmis.client.api.OperationContext;
035import org.apache.chemistry.opencmis.client.api.Policy;
036import org.apache.chemistry.opencmis.client.api.SecondaryType;
037import org.apache.chemistry.opencmis.client.api.Tree;
038import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
039import org.apache.chemistry.opencmis.client.runtime.util.AbstractPageFetcher;
040import org.apache.chemistry.opencmis.client.runtime.util.CollectionIterable;
041import org.apache.chemistry.opencmis.commons.data.Ace;
042import org.apache.chemistry.opencmis.commons.data.ContentStream;
043import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
044import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
045import org.apache.chemistry.opencmis.commons.enums.VersioningState;
046import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
047import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
048import org.nuxeo.ecm.core.api.CoreSession;
049import org.nuxeo.ecm.core.api.DocumentModel;
050import org.nuxeo.ecm.core.api.DocumentModelList;
051import org.nuxeo.ecm.core.api.IdRef;
052import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoObjectData;
053
054/**
055 * Live local CMIS Folder, which is backed by a Nuxeo folderish document.
056 */
057public class NuxeoFolder extends NuxeoFileableObject implements Folder {
058
059    public NuxeoFolder(NuxeoSession session, NuxeoObjectData data, ObjectType type,
060            List<SecondaryType> secondaryTypes) {
061        super(session, data, type, secondaryTypes);
062    }
063
064    @Override
065    public FolderType getFolderType() {
066        ObjectType objectType = getType();
067        if (objectType instanceof FolderType) {
068            return (FolderType) objectType;
069        } else {
070            throw new ClassCastException("Object type is not a folder type.");
071        }
072    }
073
074    @Override
075    public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
076            VersioningState versioningState) {
077        return createDocument(properties, contentStream, versioningState, null, null, null, session.getDefaultContext());
078    }
079
080    @Override
081    public Document createDocument(Map<String, ?> properties, ContentStream contentStream,
082            VersioningState versioningState, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
083            OperationContext context) {
084        String id = service.createDocument(getRepositoryId(), session.convertProperties(properties), getId(),
085                contentStream, versioningState, objectFactory.convertPolicies(policies),
086                objectFactory.convertAces(addAces), objectFactory.convertAces(removeAces), null);
087        // must now refetch doc
088        return (Document) session.getObject(new ObjectIdImpl(id), context);
089    }
090
091    @Override
092    public NuxeoDocument createDocumentFromSource(ObjectId source, Map<String, ?> properties,
093            VersioningState versioningState) {
094        return createDocumentFromSource(source, properties, versioningState, null, null, null,
095                session.getDefaultContext());
096    }
097
098    @Override
099    public NuxeoDocument createDocumentFromSource(ObjectId source, Map<String, ?> properties,
100            VersioningState versioningState, List<Policy> policies, List<Ace> addACEs, List<Ace> removeACEs,
101            OperationContext context) {
102        if (source == null || source.getId() == null) {
103            throw new CmisInvalidArgumentException("Invalid source: " + source);
104        }
105        if (context == null) {
106            context = session.getDefaultContext();
107        }
108        NuxeoObjectData newData = nuxeoCmisService.copy(source.getId(), getId(), properties, type, versioningState,
109                policies, addACEs, removeACEs, context);
110        return (NuxeoDocument) session.getObjectFactory().convertObject(newData, context);
111    }
112
113    @Override
114    public Folder createFolder(Map<String, ?> properties) {
115        return createFolder(properties, null, null, null, session.getDefaultContext());
116    }
117
118    @Override
119    public Folder createFolder(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
120            List<Ace> removeAces, OperationContext context) {
121        // TODO Auto-generated method stub
122        throw new UnsupportedOperationException();
123    }
124
125    @Override
126    public Policy createPolicy(Map<String, ?> properties) {
127        return createPolicy(properties, null, null, null, session.getDefaultContext());
128    }
129
130    @Override
131    public Policy createPolicy(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces,
132            List<Ace> removeAces, OperationContext context) {
133        throw new CmisNotSupportedException();
134    }
135
136    @Override
137    public Item createItem(Map<String, ?> properties) {
138        return createItem(properties, null, null, null, session.getDefaultContext());
139    }
140
141    @Override
142    public Item createItem(Map<String, ?> properties, List<Policy> policies, List<Ace> addAces, List<Ace> removeAces,
143            OperationContext context) {
144        throw new CmisNotSupportedException();
145    }
146
147    @Override
148    public List<String> deleteTree(boolean allVersions, UnfileObject unfile, boolean continueOnFailure) {
149        FailedToDeleteData failed = service.deleteTree(getRepositoryId(), getId(), Boolean.valueOf(allVersions),
150                unfile, Boolean.valueOf(continueOnFailure), null);
151        if (failed == null || failed.getIds() == null || failed.getIds().isEmpty()) {
152            return null;
153        }
154        return failed.getIds();
155    }
156
157    @Override
158    public List<ObjectType> getAllowedChildObjectTypes() {
159        // TODO Auto-generated method stub
160        throw new UnsupportedOperationException();
161    }
162
163    @Override
164    public ItemIterable<Document> getCheckedOutDocs() {
165        return getCheckedOutDocs(session.getDefaultContext());
166    }
167
168    @Override
169    public ItemIterable<Document> getCheckedOutDocs(OperationContext context) {
170        // TODO Auto-generated method stub
171        throw new UnsupportedOperationException();
172    }
173
174    @Override
175    public ItemIterable<CmisObject> getChildren() {
176        return getChildren(session.getDefaultContext());
177    }
178
179    @Override
180    public ItemIterable<CmisObject> getChildren(final OperationContext context) {
181        AbstractPageFetcher<CmisObject> pageFetcher = new AbstractPageFetcher<CmisObject>(context.getMaxItemsPerPage()) {
182            @Override
183            protected Page<CmisObject> fetchPage(long skipCount) {
184                List<CmisObject> items = new ArrayList<>();
185                DocumentModelList children = nuxeoCmisService.getCoreSession().getChildren(data.doc.getRef());
186                long totalItems = 0;
187                long skip = skipCount;
188                // TODO orderBy
189                for (DocumentModel child : children) {
190                    if (nuxeoCmisService.isFilteredOut(child)) {
191                        continue;
192                    }
193                    totalItems++;
194                    if (skip > 0) {
195                        skip--;
196                        continue;
197                    }
198                    if (items.size() > maxNumItems) {
199                        continue;
200                    }
201                    NuxeoObjectData data = new NuxeoObjectData(service, child, context);
202                    CmisObject ob = objectFactory.convertObject(data, context);
203                    items.add(ob);
204                }
205                return new Page<>(items, totalItems, totalItems > skipCount + items.size());
206            }
207        };
208        return new CollectionIterable<>(pageFetcher);
209    }
210
211    @Override
212    public List<Tree<FileableCmisObject>> getDescendants(int depth) {
213        // TODO Auto-generated method stub
214        throw new UnsupportedOperationException();
215    }
216
217    @Override
218    public List<Tree<FileableCmisObject>> getDescendants(int depth, OperationContext context) {
219        // TODO Auto-generated method stub
220        throw new UnsupportedOperationException();
221    }
222
223    @Override
224    public Folder getFolderParent() {
225        if (isRootFolder()) {
226            return null;
227        }
228        List<Folder> parents = getParents();
229        if (parents == null || parents.isEmpty()) {
230            return null;
231        }
232        return parents.get(0);
233    }
234
235    @Override
236    public String getParentId() {
237        CoreSession coreSession = data.doc.getCoreSession();
238        DocumentModel parent = coreSession.getParentDocument(new IdRef(getId()));
239        if (parent == null || nuxeoCmisService.isFilteredOut(parent)) {
240            return null;
241        }
242        return parent.getId();
243    }
244
245    @Override
246    public List<Tree<FileableCmisObject>> getFolderTree(int depth) {
247        // TODO Auto-generated method stub
248        throw new UnsupportedOperationException();
249    }
250
251    @Override
252    public List<Tree<FileableCmisObject>> getFolderTree(int depth, OperationContext context) {
253        // TODO Auto-generated method stub
254        throw new UnsupportedOperationException();
255    }
256
257    @Override
258    public String getPath() {
259        return data.doc.getPathAsString();
260    }
261
262    @Override
263    public boolean isRootFolder() {
264        return data.doc.getPath().isRoot();
265    }
266
267}