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