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