001/*
002 * (C) Copyright 2006-2018 Nuxeo (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 *     bstefanescu
018 */
019package org.nuxeo.ecm.automation.client.adapters;
020
021import java.io.IOException;
022import java.util.Arrays;
023
024import org.apache.commons.lang3.StringUtils;
025import org.nuxeo.ecm.automation.client.Constants;
026import org.nuxeo.ecm.automation.client.OperationRequest;
027import org.nuxeo.ecm.automation.client.Session;
028import org.nuxeo.ecm.automation.client.model.Blob;
029import org.nuxeo.ecm.automation.client.model.Blobs;
030import org.nuxeo.ecm.automation.client.model.DocRef;
031import org.nuxeo.ecm.automation.client.model.Document;
032import org.nuxeo.ecm.automation.client.model.Documents;
033import org.nuxeo.ecm.automation.client.model.FileBlob;
034import org.nuxeo.ecm.automation.client.model.PathRef;
035import org.nuxeo.ecm.automation.client.model.PropertyMap;
036
037/**
038 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
039 */
040public class DocumentService {
041
042    public static final String FetchDocument = "Repository.GetDocument";
043
044    public static final String CreateDocument = "Document.Create";
045
046    public static final String DeleteDocument = "Document.Delete";
047
048    public static final String CopyDocument = "Document.Copy";
049
050    public static final String MoveDocument = "Document.Move";
051
052    public static final String GetDocumentChildren = "Document.GetChildren";
053
054    public static final String GetDocumentChild = "Document.GetChild";
055
056    public static final String GetDocumentParent = "Document.GetParent";
057
058    public static final String Query = "Repository.Query";
059
060    public static final String SetPermission = "Document.AddACE";
061
062    public static final String RemoveAcl = "Document.RemoveACL";
063
064    public static final String SetDocumentState = "Document.FollowLifecycleTransition";
065
066    public static final String LockDocument = "Document.Lock";
067
068    public static final String UnlockDocument = "Document.Unlock";
069
070    public static final String SetProperty = "Document.SetProperty";
071
072    public static final String RemoveProperty = "Document.RemoveProperty";
073
074    public static final String UpdateDocument = "Document.Update";
075
076    public static final String PublishDocument = "Document.Publish";
077
078    public static final String CreateRelation = "Document.AddRelation";
079
080    public static final String GetRelations = "Document.GetLinkedDocuments";
081
082    public static final String SetBlob = "Blob.AttachOnDocument";
083
084    public static final String RemoveBlob = "Blob.RemoveFromDocument";
085
086    public static final String GetBlob = "Document.GetBlob";
087
088    public static final String GetBlobs = "Document.GetBlobsByProperty";
089
090    public static final String CreateVersion = "Document.CreateVersion";
091
092    public static final String FireEvent = "Event.Fire";
093
094    // The following are not yet implemented
095    public static final String CheckOut = "Document.CheckOut";
096
097    public static final String CheckIn = "Document.CheckIn";
098
099    // //TODO GetAcl?
100    protected Session session;
101
102    public DocumentService(Session session) {
103        this.session = session;
104    }
105
106    public Session getSession() {
107        return session;
108    }
109
110    public Document getDocument(String ref) throws IOException {
111        return getDocument(DocRef.newRef(ref), null);
112    }
113
114    /**
115     * @since 5.7
116     * @param document document to fetch
117     * @param schemas schemas related to the document to fetch (* for all)
118     * @return the document returned by server
119     */
120    public Document getDocument(Document document, String... schemas) throws IOException {
121        return getDocument(new DocRef(document.getId()), StringUtils.join(Arrays.asList(schemas), ","));
122    }
123
124    public Document getDocument(DocRef ref) throws IOException {
125        return getDocument(ref, null);
126    }
127
128    public Document getDocument(DocRef ref, String schemas) throws IOException {
129        OperationRequest req = session.newRequest(FetchDocument).set("value", ref);
130        if (schemas != null) {
131            req.setHeader(Constants.HEADER_NX_SCHEMAS, schemas);
132        }
133        return (Document) req.execute();
134    }
135
136    public Document getRootDocument() throws IOException {
137        return getDocument(new PathRef("/"));
138    }
139
140    /**
141     * @since 5.7
142     * @param parent can be PathRef or IdRef
143     * @param document the document to create
144     * @return the document created
145     */
146    public Document createDocument(String parent, Document document) throws IOException {
147        return createDocument(DocRef.newRef(parent), document.getType(), document.getId(), document.getDirties());
148    }
149
150    public Document createDocument(DocRef parent, String type, String name) throws IOException {
151        return createDocument(parent, type, name, null);
152    }
153
154    /**
155     * THIS METHOD IS PART OF PRIVATE API NOW, DON'T USE IT.
156     *
157     * @deprecated since 9.1 use {@link #createDocument(String, Document)} or
158     *             {@link #createDocument(DocRef, String, String)} instead as instances of {@link PropertyMap} is now
159     *             read-only.
160     */
161    @Deprecated
162    public Document createDocument(DocRef parent, String type, String name, PropertyMap properties) throws IOException {
163        OperationRequest req = session.newRequest(CreateDocument).setInput(parent).set("type", type).set("name", name);
164        if (properties != null && !properties.isEmpty()) {
165            req.set("properties", properties);
166        }
167        return (Document) req.execute();
168    }
169
170    /**
171     * @since 5.7
172     * @param document the document to remove
173     */
174    public void remove(Document document) throws IOException {
175        remove(new DocRef(document.getId()));
176    }
177
178    public void remove(DocRef doc) throws IOException {
179        session.newRequest(DeleteDocument).setInput(doc).execute();
180    }
181
182    public void remove(String ref) throws IOException {
183        session.newRequest(DeleteDocument).setInput(DocRef.newRef(ref)).execute();
184    }
185
186    public Document copy(DocRef src, DocRef targetParent) throws IOException {
187        return copy(src, targetParent, null);
188    }
189
190    public Document copy(DocRef src, DocRef targetParent, String name) throws IOException {
191        OperationRequest req = session.newRequest(CopyDocument).setInput(src).set("target", targetParent);
192        if (name != null) {
193            req.set("name", name);
194        }
195        return (Document) req.execute();
196    }
197
198    public Document move(DocRef src, DocRef targetParent) throws IOException {
199        return move(src, targetParent, null);
200    }
201
202    public Document move(DocRef src, DocRef targetParent, String name) throws IOException {
203        OperationRequest req = session.newRequest(MoveDocument).setInput(src).set("target", targetParent);
204        if (name != null) {
205            req.set("name", name);
206        }
207        return (Document) req.execute();
208    }
209
210    public Documents getChildren(DocRef docRef) throws IOException {
211        return (Documents) session.newRequest(GetDocumentChildren).setInput(docRef).execute();
212    }
213
214    public Document getChild(DocRef docRef, String name) throws IOException {
215        return (Document) session.newRequest(GetDocumentChild).setInput(docRef).set("name", name).execute();
216    }
217
218    public Document getParent(DocRef docRef) throws IOException {
219        return (Document) session.newRequest(GetDocumentParent).setInput(docRef).execute();
220    }
221
222    public Documents getParent(DocRef docRef, String type) throws IOException {
223        return (Documents) session.newRequest(GetDocumentParent).setInput(docRef).set("type", type).execute();
224    }
225
226    public Documents query(String query) throws IOException {
227        return (Documents) session.newRequest(Query).set("query", query).execute();
228    }
229
230    public Document setPermission(DocRef doc, String user, String permission) throws IOException {
231        return setPermission(doc, user, permission, null, true);
232    }
233
234    public Document setPermission(DocRef doc, String user, String permission, boolean granted) throws IOException {
235        return setPermission(doc, user, permission, null, granted);
236    }
237
238    public Document setPermission(DocRef doc, String user, String permission, String acl, boolean granted)
239            throws IOException {
240        OperationRequest req = session.newRequest(SetPermission)
241                                      .setInput(doc)
242                                      .set("user", user)
243                                      .set("permission", permission)
244                                      .set("grant", granted);
245        if (acl != null) {
246            req.set("acl", acl);
247        }
248        return (Document) req.execute();
249    }
250
251    public Document removeAcl(DocRef doc, String acl) throws IOException {
252        return (Document) session.newRequest(RemoveAcl).setInput(doc).set("acl", acl).execute();
253    }
254
255    public Document setState(DocRef doc, String state) throws IOException {
256        return (Document) session.newRequest(SetDocumentState).setInput(doc).set("value", state).execute();
257    }
258
259    public Document lock(DocRef doc) throws IOException {
260        return lock(doc, null);
261    }
262
263    public Document lock(DocRef doc, String lock) throws IOException {
264        OperationRequest req = session.newRequest(LockDocument).setInput(doc);
265        if (lock != null) {
266            req.set("owner", lock);
267        }
268        return (Document) req.execute();
269    }
270
271    public Document unlock(DocRef doc) throws IOException {
272        return (Document) session.newRequest(UnlockDocument).setInput(doc).execute();
273    }
274
275    // TODO: value Serializable?
276    public Document setProperty(DocRef doc, String key, String value) throws IOException {
277        return (Document) session.newRequest(SetProperty).setInput(doc).set("xpath", key).set("value", value).execute();
278    }
279
280    public Document removeProperty(DocRef doc, String key) throws IOException {
281        return (Document) session.newRequest(RemoveProperty).setInput(doc).set("xpath", key).execute();
282    }
283
284    /**
285     * This method sends the dirty properties to server
286     *
287     * @since 5.7
288     * @param document the document to update
289     * @return the document returned by the server
290     */
291    public Document update(Document document) throws IOException {
292        return (Document) session.newRequest(UpdateDocument)
293                                 .setInput(document)
294                                 .set("properties", document.getDirties())
295                                 .execute();
296    }
297
298    /**
299     * @deprecated since 9.1 use {@link #update(Document)} instead as instances of {@link PropertyMap} is now read-only.
300     */
301    @Deprecated
302    public Document update(DocRef doc, PropertyMap properties) throws IOException {
303        return (Document) session.newRequest(UpdateDocument).setInput(doc).set("properties", properties).execute();
304    }
305
306    public Document publish(DocRef doc, DocRef section) throws IOException {
307        return publish(doc, section, true);
308    }
309
310    public Document publish(DocRef doc, DocRef section, boolean override) throws IOException {
311        return (Document) session.newRequest(PublishDocument)
312                                 .setInput(doc)
313                                 .set("target", section)
314                                 .set("override", override)
315                                 .execute();
316    }
317
318    public Document createRelation(DocRef subject, String predicate, DocRef object) throws IOException {
319        return (Document) session.newRequest(CreateRelation)
320                                 .setInput(subject)
321                                 .set("object", object)
322                                 .set("predicate", predicate)
323                                 .execute();
324    }
325
326    public Documents getRelations(DocRef doc, String predicate) throws IOException {
327        return getRelations(doc, predicate, true);
328    }
329
330    public Documents getRelations(DocRef doc, String predicate, boolean outgoing) throws IOException {
331        return (Documents) session.newRequest(GetRelations)
332                                  .setInput(doc)
333                                  .set("predicate", predicate)
334                                  .set("outgoing", outgoing)
335                                  .execute();
336    }
337
338    /**
339     * @since 5.5
340     */
341    public Documents getRelations(DocRef doc, String predicate, boolean outgoing, String graphName) throws IOException {
342        return (Documents) session.newRequest(GetRelations)
343                                  .setInput(doc)
344                                  .set("predicate", predicate)
345                                  .set("outgoing", outgoing)
346                                  .set("graphName", graphName)
347                                  .execute();
348    }
349
350    public void setBlob(DocRef doc, Blob blob) throws IOException {
351        setBlob(doc, blob, null);
352    }
353
354    public void setBlob(DocRef doc, Blob blob, String xpath) throws IOException {
355        OperationRequest req = session.newRequest(SetBlob).setInput(blob).set("document", doc);
356        if (xpath != null) {
357            req.set("xpath", xpath);
358        }
359        req.setHeader(Constants.HEADER_NX_VOIDOP, "true");
360        req.execute();
361    }
362
363    public void removeBlob(DocRef doc) throws IOException {
364        removeBlob(doc, null);
365    }
366
367    public void removeBlob(DocRef doc, String xpath) throws IOException {
368        OperationRequest req = session.newRequest(RemoveBlob).setInput(doc);
369        if (xpath != null) {
370            req.set("xpath", xpath);
371        }
372        req.setHeader(Constants.HEADER_NX_VOIDOP, "true");
373        req.execute();
374    }
375
376    public FileBlob getBlob(DocRef doc) throws IOException {
377        return getBlob(doc, null);
378    }
379
380    public FileBlob getBlob(DocRef doc, String xpath) throws IOException {
381        OperationRequest req = session.newRequest(GetBlob).setInput(doc);
382        if (xpath != null) {
383            req.set("xpath", xpath);
384        }
385        return (FileBlob) req.execute();
386    }
387
388    public Blobs getBlobs(DocRef doc) throws IOException {
389        return getBlobs(doc, null);
390    }
391
392    public Blobs getBlobs(DocRef doc, String xpath) throws IOException {
393        OperationRequest req = session.newRequest(GetBlobs).setInput(doc);
394        if (xpath != null) {
395            req.set("xpath", xpath);
396        }
397        return (Blobs) req.execute();
398    }
399
400    public Document createVersion(DocRef doc) throws IOException {
401        return createVersion(doc, null);
402    }
403
404    /**
405     * Increment is one of "None", "Major", "Minor". If null the server default will be used. See
406     * {@link VersionIncrement}
407     */
408    public Document createVersion(DocRef doc, String increment) throws IOException {
409        OperationRequest req = session.newRequest(CreateVersion).setInput(doc);
410        if (increment != null) {
411            req.set("increment", increment);
412        }
413        return (Document) req.execute();
414    }
415
416    public void fireEvent(String event) throws IOException {
417        fireEvent(null, event);
418    }
419
420    public void fireEvent(DocRef doc, String event) throws IOException {
421        OperationRequest req = session.newRequest(CreateVersion).setInput(doc);
422        req.setHeader(Constants.HEADER_NX_VOIDOP, "true");
423        req.execute();
424    }
425}