001/*
002 * (C) Copyright 2006-2017 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 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.storage.sql;
020
021import java.io.Serializable;
022import java.util.Collection;
023import java.util.List;
024import java.util.Map;
025
026import javax.resource.cci.Connection;
027
028import org.nuxeo.ecm.core.api.IterableQueryResult;
029import org.nuxeo.ecm.core.api.PartialList;
030import org.nuxeo.ecm.core.api.ScrollResult;
031import org.nuxeo.ecm.core.model.LockManager;
032import org.nuxeo.ecm.core.query.QueryFilter;
033
034/**
035 * The session is the main high level access point to data from the underlying database.
036 *
037 * @author Florent Guillaume
038 */
039public interface Session extends Connection {
040
041    /**
042     * Gets the low-level Mapper for this session.
043     *
044     * @return the mapper
045     */
046    Mapper getMapper();
047
048    /**
049     * Checks if the session is live (not closed).
050     *
051     * @return {@code true} if the session is live
052     */
053    boolean isLive();
054
055    /**
056     * Gets the session repository name.
057     *
058     * @return the repository name
059     */
060    String getRepositoryName();
061
062    /**
063     * Gets the {@link Model} associated to this session.
064     *
065     * @return the model
066     */
067    Model getModel();
068
069    /**
070     * Saves the modifications to persistent storage.
071     * <p>
072     * Modifications will be actually written only upon transaction commit.
073     */
074    void save();
075
076    /**
077     * Gets the root node of the repository.
078     *
079     * @return the root node
080     */
081    Node getRootNode();
082
083    /**
084     * Gets a node given its id.
085     *
086     * @param id the id
087     * @return the node, or {@code null} if not found
088     */
089    Node getNodeById(Serializable id);
090
091    /**
092     * Gets several nodes given their ids.
093     *
094     * @param ids the ids
095     * @return the nodes, in the same order as the ids, with elements being {@code null} if not found
096     */
097    List<Node> getNodesByIds(Collection<Serializable> ids);
098
099    /**
100     * Gets a node given its absolute path, or given an existing node and a relative path.
101     *
102     * @param path the path
103     * @param node the node (ignored for absolute paths)
104     * @return the node, or {@code null} if not found
105     */
106    Node getNodeByPath(String path, Node node);
107
108    /**
109     * Adds a mixin to a node.
110     * <p>
111     * Does nothing if the mixin was already present on the node.
112     *
113     * @param node the node
114     * @param mixin the mixin name
115     * @return {@code true} if the mixin was added, or {@code false} if it is already present
116     * @since 5.8
117     */
118    boolean addMixinType(Node node, String mixin);
119
120    /**
121     * Removes a mixin from a node.
122     * <p>
123     * It's not possible to remove a mixin coming from the primary type.
124     *
125     * @param node the node
126     * @param mixin the mixin
127     * @return {@code true} if the mixin was removed, or {@code false} if it isn't present or is present on the type or
128     *         does not exist
129     * @since 5.8
130     */
131    boolean removeMixinType(Node node, String mixin);
132
133    /**
134     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
135     * requested within the {@code keepAliveSeconds} delay.
136     *
137     * @since 8.4
138     */
139    ScrollResult<String> scroll(String query, int batchSize, int keepAliveSeconds);
140
141    /**
142     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
143     * requested within the {@code keepAliveSeconds} delay.
144     *
145     * @since 10.3
146     */
147    ScrollResult<String> scroll(String query, QueryFilter queryFilter, int batchSize, int keepAliveSeconds);
148
149    /**
150     * Get the next batch of results containing id of documents, the {@code scrollId} is part of the previous
151     * {@link ScrollResult} response.
152     *
153     * @since 8.4
154     */
155    ScrollResult<String> scroll(String scrollId);
156
157    /**
158     * Interface for a class that knows how to resolve a node path into a node id.
159     */
160    interface PathResolver {
161        /**
162         * Returns the node id for a given path.
163         *
164         * @param path the node path
165         * @return the node id, or {@code null}
166         */
167        Serializable getIdForPath(String path);
168    }
169
170    /**
171     * Gets the parent of a node.
172     * <p>
173     * The root has a {@code null} parent.
174     *
175     * @param node the node
176     * @return the parent node, or {@code null} for the root's parent
177     */
178    Node getParentNode(Node node);
179
180    /**
181     * Gets the absolute path of a node.
182     *
183     * @param node the node
184     * @return the path
185     */
186    String getPath(Node node);
187
188    /**
189     * Checks if a child node with the given name exists.
190     * <p>
191     * There are two kinds of children, the regular children documents and the complex properties. The {@code boolean}
192     * {@value #complexProp} allows a choice between those.
193     *
194     * @param parent the parent node
195     * @param name the child name
196     * @param complexProp whether to check complex properties or regular children
197     * @return {@code true} if a child node with that name exists
198     */
199    boolean hasChildNode(Node parent, String name, boolean complexProp);
200
201    /**
202     * Gets a child node given its parent and name.
203     *
204     * @param parent the parent node
205     * @param name the child name
206     * @param complexProp whether to check complex properties or regular children
207     * @return the child node, or {@code null} is not found
208     */
209    Node getChildNode(Node parent, String name, boolean complexProp);
210
211    /**
212     * Checks it a node has children.
213     *
214     * @param parent the parent node
215     * @param complexProp whether to check complex properties or regular children
216     * @return {@code true} if the parent has children
217     */
218    boolean hasChildren(Node parent, boolean complexProp);
219
220    /**
221     * Gets the children of a node.
222     *
223     * @param parent the parent node
224     * @param name the children name to get (for lists of complex properties), or {@code null} for all
225     * @param complexProp whether to check complex properties or regular children
226     * @return the collection of children
227     */
228    List<Node> getChildren(Node parent, String name, boolean complexProp);
229
230    /**
231     * Creates a new child node.
232     *
233     * @param parent the parent to which the child is added
234     * @param name the child name
235     * @param pos the child position, or {@code null}
236     * @param typeName the child type
237     * @param complexProp whether this is a complex property ({@code true}) or a regular child ({@code false})
238     * @return the new node
239     */
240    Node addChildNode(Node parent, String name, Long pos, String typeName, boolean complexProp);
241
242    /**
243     * Creates a new child node with given id (used for import).
244     *
245     * @param id the id
246     * @param parent the parent to which the child is added
247     * @param name the child name
248     * @param pos the child position, or {@code null}
249     * @param typeName the child type
250     * @param complexProp whether this is a complex property ({@code true}) or a regular child ({@code false})
251     * @return the new node
252     */
253    Node addChildNode(Serializable id, Node parent, String name, Long pos, String typeName, boolean complexProp);
254
255    /**
256     * Creates a proxy for a version node.
257     *
258     * @param targetId the target id
259     * @param versionSeriesId the version series id
260     * @param parent the parent to which the proxy is added
261     * @param name the proxy name
262     * @param pos the proxy position
263     * @return the new proxy node
264     */
265    Node addProxy(Serializable targetId, Serializable versionSeriesId, Node parent, String name, Long pos);
266
267    /**
268     * Sets a proxies' target.
269     *
270     * @param proxy the proxy
271     * @param targetId the new target id
272     * @since 5.5
273     */
274    void setProxyTarget(Node proxy, Serializable targetId);
275
276    /**
277     * Removes a node from the storage.
278     * <p>
279     * This is much more complex that removing a property node ( {@link #removePropertyNode}).
280     *
281     * @param node the node to remove
282     * @see {@link #removePropertyNode}
283     */
284    void removeNode(Node node);
285
286    /**
287     * Removes a property node from the storage.
288     * <p>
289     * This is much less complex that removing a generic document node ( {@link #removeNode}).
290     *
291     * @param node the property node to remove
292     * @see {@link #removeNode}
293     */
294    void removePropertyNode(Node node);
295
296    /**
297     * Order the given source child node before the destination child node. The source node will be placed before the
298     * destination one. If destination is {@code null}, the source node will be appended at the end of the children
299     * list.
300     *
301     * @param parent the parent node
302     * @param source the child node to move
303     * @param dest the child node before which to place the source node, or {@code null} to move at the end
304     */
305    void orderBefore(Node parent, Node source, Node dest);
306
307    /**
308     * Moves a node to a new location with a new name.
309     * <p>
310     * A {@link #save} is automatically done first.
311     *
312     * @param source the node to move
313     * @param parent the new parent to which the node is moved
314     * @param name the new node name
315     * @return the moved node
316     */
317    Node move(Node source, Node parent, String name);
318
319    /**
320     * Copies a node to a new location with a new name.
321     * <p>
322     * A {@link #save} is automatically done first.
323     *
324     * @param source the node to copy
325     * @param parent the new parent to which the node is copied
326     * @param name the new node name
327     * @return the copied node
328     */
329    Node copy(Node source, Node parent, String name);
330
331    /**
332     * Checks in a checked-out node: creates a new version with a copy of its information.
333     * <p>
334     * A {@link #save} is automatically done first.
335     *
336     * @param node the node to check in
337     * @param label the label for the version
338     * @param checkinComment the description for the version
339     * @return the created version
340     */
341    Node checkIn(Node node, String label, String checkinComment);
342
343    /**
344     * Checks out a checked-in node.
345     *
346     * @param node the node to check out
347     */
348    void checkOut(Node node);
349
350    /**
351     * Restores a node to a given version.
352     * <p>
353     * The restored node is checked in.
354     *
355     * @param node the node to restore
356     * @param version the version to restore from
357     */
358    void restore(Node node, Node version);
359
360    /**
361     * Gets a version given its version series id and label.
362     *
363     * @param versionSeriesId the version series id
364     * @param label the label
365     * @return the version node, or {@code null} if not found
366     */
367    Node getVersionByLabel(Serializable versionSeriesId, String label);
368
369    /**
370     * Gets all the versions for a given version series id.
371     * <p>
372     * A {@link #save} is automatically done first.
373     *
374     * @param versionSeriesId the version series id
375     * @return the list of versions
376     */
377    List<Node> getVersions(Serializable versionSeriesId);
378
379    /**
380     * Gets the last version for a given version series id.
381     * <p>
382     * A {@link #save} is automatically done first.
383     *
384     * @param versionSeriesId the version series id
385     * @return the last version, or {@code null} if no versions exist
386     */
387    Node getLastVersion(Serializable versionSeriesId);
388
389    /**
390     * Finds the proxies for a document. If the parent is not null, the search will be limited to its direct children.
391     * <p>
392     * If the document is a version, then only proxies to that version will be looked up.
393     * <p>
394     * Otherwise all proxies to the same version series than the document are retrieved.
395     * <p>
396     * A {@link #save} is automatically done first.
397     *
398     * @param document the document
399     * @param parent the parent, or {@code null}
400     * @return the list of proxies
401     */
402    List<Node> getProxies(Node document, Node parent);
403
404    /**
405     * Finds the proxies for a document. (The document may be a version or a live document)
406     * @param document the document
407     * @return the list of proxies,  or an empty list
408     * @since 10.2
409     */
410    List<Node> getProxies(Node document);
411
412    /**
413     * Makes a NXQL query to the database.
414     *
415     * @param query the query
416     * @param queryFilter the query filter
417     * @param countTotal if {@code true}, also count the total size without offset/limit
418     * @return the resulting list with total size included
419     */
420    PartialList<Serializable> query(String query, QueryFilter queryFilter, boolean countTotal);
421
422    /**
423     * Makes a query to the database.
424     *
425     * @param query the query
426     * @param queryType the query type
427     * @param queryFilter the query filter
428     * @param countUpTo if {@code -1}, also count the total size without offset/limit.<br>
429     *            If {@code 0}, don't count the total size.<br>
430     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
431     *            {@code -1}.
432     * @return the resulting list with total size included
433     * @since 5.6
434     */
435    PartialList<Serializable> query(String query, String queryType, QueryFilter queryFilter, long countUpTo);
436
437    /**
438     * Makes a query to the database and returns an iterable (which must be closed when done).
439     *
440     * @param query the query
441     * @param queryType the query type
442     * @param queryFilter the query filter
443     * @param params optional query-type-dependent parameters
444     * @return an iterable, which <b>must</b> be closed when done
445     */
446    IterableQueryResult queryAndFetch(String query, String queryType, QueryFilter queryFilter, Object... params);
447
448    /**
449     * Makes a query to the database and returns an iterable (which must be closed when done).
450     *
451     * @param query the query
452     * @param queryType the query type
453     * @param queryFilter the query filter
454     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
455     * @param params optional query-type-dependent parameters
456     * @return an iterable, which <b>must</b> be closed when done
457     * @since 7.10-HF04, 8.2
458     */
459    IterableQueryResult queryAndFetch(String query, String queryType, QueryFilter queryFilter,
460            boolean distinctDocuments, Object... params);
461
462    /**
463     * Makes a query to the database.
464     *
465     * @param query the query
466     * @param queryType the query type
467     * @param queryFilter the query filter
468     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
469     * @param countUpTo if {@code -1}, also count the total size without offset/limit.<br>
470     *            If {@code 0}, don't count the total size.<br>
471     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
472     *            {@code -1}.
473     * @param params optional query-type-dependent parameters
474     * @return a projection
475     * @since 7.10-HF-25, 8.10-HF06, 9.2
476     */
477    PartialList<Map<String,Serializable>> queryProjection(String query, String queryType, QueryFilter queryFilter, boolean distinctDocuments,
478            long countUpTo, Object[] params);
479
480    /**
481     * Gets the lock manager for this session.
482     *
483     * @return the lock manager
484     * @since 7.4
485     */
486    LockManager getLockManager();
487
488    /**
489     * Read ACLs are optimized ACLs for the read permission, they need to be updated after document creation or ACL
490     * change.
491     * <p>
492     * This method flag the current session, the read ACLs update will be done automatically at save time.
493     */
494    void requireReadAclsUpdate();
495
496    /**
497     * Update only the read ACLs that have changed.
498     */
499    void updateReadAcls();
500
501    /**
502     * Rebuild the read ACLs for the whole repository.
503     */
504    void rebuildReadAcls();
505
506    /**
507     * Gets the fulltext extracted from the binary fields.
508     *
509     * @since 5.9.3
510     */
511    Map<String, String> getBinaryFulltext(Serializable id);
512
513    /**
514     * Checks if change token management is enabled.
515     *
516     * @since 9.1
517     */
518    boolean isChangeTokenEnabled();
519
520    /**
521     * Marks the document as being modified by a user change.
522     * <p>
523     * This causes an additional change token increment and check during save.
524     *
525     * @param id the document id
526     * @since 9.2
527     */
528    void markUserChange(Serializable id);
529
530}