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 containing id of documents, next batch must be
134     * requested within the {@code keepAliveSeconds} delay.
135     *
136     * @since 8.4
137     */
138    ScrollResult<String> scroll(String query, int batchSize, int keepAliveSeconds);
139
140    /**
141     * Get the next batch of results containing id of documents, the {@code scrollId} is part of the previous
142     * {@link ScrollResult} response.
143     *
144     * @since 8.4
145     */
146    ScrollResult<String> scroll(String scrollId);
147
148    /**
149     * Interface for a class that knows how to resolve a node path into a node id.
150     */
151    interface PathResolver {
152        /**
153         * Returns the node id for a given path.
154         *
155         * @param path the node path
156         * @return the node id, or {@code null}
157         */
158        Serializable getIdForPath(String path);
159    }
160
161    /**
162     * Gets the parent of a node.
163     * <p>
164     * The root has a {@code null} parent.
165     *
166     * @param node the node
167     * @return the parent node, or {@code null} for the root's parent
168     */
169    Node getParentNode(Node node);
170
171    /**
172     * Gets the absolute path of a node.
173     *
174     * @param node the node
175     * @return the path
176     */
177    String getPath(Node node);
178
179    /**
180     * Checks if a child node with the given name exists.
181     * <p>
182     * There are two kinds of children, the regular children documents and the complex properties. The {@code boolean}
183     * {@value #complexProp} allows a choice between those.
184     *
185     * @param parent the parent node
186     * @param name the child name
187     * @param complexProp whether to check complex properties or regular children
188     * @return {@code true} if a child node with that name exists
189     */
190    boolean hasChildNode(Node parent, String name, boolean complexProp);
191
192    /**
193     * Gets a child node given its parent and name.
194     *
195     * @param parent the parent node
196     * @param name the child name
197     * @param complexProp whether to check complex properties or regular children
198     * @return the child node, or {@code null} is not found
199     */
200    Node getChildNode(Node parent, String name, boolean complexProp);
201
202    /**
203     * Checks it a node has children.
204     *
205     * @param parent the parent node
206     * @param complexProp whether to check complex properties or regular children
207     * @return {@code true} if the parent has children
208     */
209    boolean hasChildren(Node parent, boolean complexProp);
210
211    /**
212     * Gets the children of a node.
213     *
214     * @param parent the parent node
215     * @param name the children name to get (for lists of complex properties), or {@code null} for all
216     * @param complexProp whether to check complex properties or regular children
217     * @return the collection of children
218     */
219    List<Node> getChildren(Node parent, String name, boolean complexProp);
220
221    /**
222     * Creates a new child node.
223     *
224     * @param parent the parent to which the child is added
225     * @param name the child name
226     * @param pos the child position, or {@code null}
227     * @param typeName the child type
228     * @param complexProp whether this is a complex property ({@code true}) or a regular child ({@code false})
229     * @return the new node
230     */
231    Node addChildNode(Node parent, String name, Long pos, String typeName, boolean complexProp);
232
233    /**
234     * Creates a new child node with given id (used for import).
235     *
236     * @param id the id
237     * @param parent the parent to which the child is added
238     * @param name the child name
239     * @param pos the child position, or {@code null}
240     * @param typeName the child type
241     * @param complexProp whether this is a complex property ({@code true}) or a regular child ({@code false})
242     * @return the new node
243     */
244    Node addChildNode(Serializable id, Node parent, String name, Long pos, String typeName, boolean complexProp);
245
246    /**
247     * Creates a proxy for a version node.
248     *
249     * @param targetId the target id
250     * @param versionSeriesId the version series id
251     * @param parent the parent to which the proxy is added
252     * @param name the proxy name
253     * @param pos the proxy position
254     * @return the new proxy node
255     */
256    Node addProxy(Serializable targetId, Serializable versionSeriesId, Node parent, String name, Long pos);
257
258    /**
259     * Sets a proxies' target.
260     *
261     * @param proxy the proxy
262     * @param targetId the new target id
263     * @since 5.5
264     */
265    void setProxyTarget(Node proxy, Serializable targetId);
266
267    /**
268     * Removes a node from the storage.
269     * <p>
270     * This is much more complex that removing a property node ( {@link #removePropertyNode}).
271     *
272     * @param node the node to remove
273     * @see {@link #removePropertyNode}
274     */
275    void removeNode(Node node);
276
277    /**
278     * Removes a property node from the storage.
279     * <p>
280     * This is much less complex that removing a generic document node ( {@link #removeNode}).
281     *
282     * @param node the property node to remove
283     * @see {@link #removeNode}
284     */
285    void removePropertyNode(Node node);
286
287    /**
288     * Order the given source child node before the destination child node. The source node will be placed before the
289     * destination one. If destination is {@code null}, the source node will be appended at the end of the children
290     * list.
291     *
292     * @param parent the parent node
293     * @param source the child node to move
294     * @param dest the child node before which to place the source node, or {@code null} to move at the end
295     */
296    void orderBefore(Node parent, Node source, Node dest);
297
298    /**
299     * Moves a node to a new location with a new name.
300     * <p>
301     * A {@link #save} is automatically done first.
302     *
303     * @param source the node to move
304     * @param parent the new parent to which the node is moved
305     * @param name the new node name
306     * @return the moved node
307     */
308    Node move(Node source, Node parent, String name);
309
310    /**
311     * Copies a node to a new location with a new name.
312     * <p>
313     * A {@link #save} is automatically done first.
314     *
315     * @param source the node to copy
316     * @param parent the new parent to which the node is copied
317     * @param name the new node name
318     * @return the copied node
319     */
320    Node copy(Node source, Node parent, String name);
321
322    /**
323     * Checks in a checked-out node: creates a new version with a copy of its information.
324     * <p>
325     * A {@link #save} is automatically done first.
326     *
327     * @param node the node to check in
328     * @param label the label for the version
329     * @param checkinComment the description for the version
330     * @return the created version
331     */
332    Node checkIn(Node node, String label, String checkinComment);
333
334    /**
335     * Checks out a checked-in node.
336     *
337     * @param node the node to check out
338     */
339    void checkOut(Node node);
340
341    /**
342     * Restores a node to a given version.
343     * <p>
344     * The restored node is checked in.
345     *
346     * @param node the node to restore
347     * @param version the version to restore from
348     */
349    void restore(Node node, Node version);
350
351    /**
352     * Gets a version given its version series id and label.
353     *
354     * @param versionSeriesId the version series id
355     * @param label the label
356     * @return the version node, or {@code null} if not found
357     */
358    Node getVersionByLabel(Serializable versionSeriesId, String label);
359
360    /**
361     * Gets all the versions for a given version series id.
362     * <p>
363     * A {@link #save} is automatically done first.
364     *
365     * @param versionSeriesId the version series id
366     * @return the list of versions
367     */
368    List<Node> getVersions(Serializable versionSeriesId);
369
370    /**
371     * Gets the last version for a given version series id.
372     * <p>
373     * A {@link #save} is automatically done first.
374     *
375     * @param versionSeriesId the version series id
376     * @return the last version, or {@code null} if no versions exist
377     */
378    Node getLastVersion(Serializable versionSeriesId);
379
380    /**
381     * Finds the proxies for a document. If the parent is not null, the search will be limited to its direct children.
382     * <p>
383     * If the document is a version, then only proxies to that version will be looked up.
384     * <p>
385     * Otherwise all proxies to the same version series than the document are retrieved.
386     * <p>
387     * A {@link #save} is automatically done first.
388     *
389     * @param document the document
390     * @param parent the parent, or {@code null}
391     * @return the list of proxies
392     */
393    List<Node> getProxies(Node document, Node parent);
394
395    /**
396     * Makes a NXQL query to the database.
397     *
398     * @param query the query
399     * @param queryFilter the query filter
400     * @param countTotal if {@code true}, also count the total size without offset/limit
401     * @return the resulting list with total size included
402     */
403    PartialList<Serializable> query(String query, QueryFilter queryFilter, boolean countTotal);
404
405    /**
406     * Makes a query to the database.
407     *
408     * @param query the query
409     * @param queryType the query type
410     * @param queryFilter the query filter
411     * @param countUpTo if {@code -1}, also count the total size without offset/limit.<br>
412     *            If {@code 0}, don't count the total size.<br>
413     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
414     *            {@code -1}.
415     * @return the resulting list with total size included
416     * @since 5.6
417     */
418    PartialList<Serializable> query(String query, String queryType, QueryFilter queryFilter, long countUpTo);
419
420    /**
421     * Makes a query to the database and returns an iterable (which must be closed when done).
422     *
423     * @param query the query
424     * @param queryType the query type
425     * @param queryFilter the query filter
426     * @param params optional query-type-dependent parameters
427     * @return an iterable, which <b>must</b> be closed when done
428     */
429    IterableQueryResult queryAndFetch(String query, String queryType, QueryFilter queryFilter, Object... params);
430
431    /**
432     * Makes a query to the database and returns an iterable (which must be closed when done).
433     *
434     * @param query the query
435     * @param queryType the query type
436     * @param queryFilter the query filter
437     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
438     * @param params optional query-type-dependent parameters
439     * @return an iterable, which <b>must</b> be closed when done
440     * @since 7.10-HF04, 8.2
441     */
442    IterableQueryResult queryAndFetch(String query, String queryType, QueryFilter queryFilter,
443            boolean distinctDocuments, Object... params);
444
445    /**
446     * Makes a query to the database.
447     *
448     * @param query the query
449     * @param queryType the query type
450     * @param queryFilter the query filter
451     * @param distinctDocuments if {@code true} then a maximum of one row per document will be returned
452     * @param countUpTo if {@code -1}, also count the total size without offset/limit.<br>
453     *            If {@code 0}, don't count the total size.<br>
454     *            If {@code n}, count the total number if there are less than n documents otherwise set the size to
455     *            {@code -1}.
456     * @param params optional query-type-dependent parameters
457     * @return a projection
458     * @since 7.10-HF-25, 8.10-HF06, 9.2
459     */
460    PartialList<Map<String,Serializable>> queryProjection(String query, String queryType, QueryFilter queryFilter, boolean distinctDocuments,
461            long countUpTo, Object[] params);
462
463    /**
464     * Gets the lock manager for this session.
465     *
466     * @return the lock manager
467     * @since 7.4
468     */
469    LockManager getLockManager();
470
471    /**
472     * Read ACLs are optimized ACLs for the read permission, they need to be updated after document creation or ACL
473     * change.
474     * <p>
475     * This method flag the current session, the read ACLs update will be done automatically at save time.
476     */
477    void requireReadAclsUpdate();
478
479    /**
480     * Update only the read ACLs that have changed.
481     */
482    void updateReadAcls();
483
484    /**
485     * Rebuild the read ACLs for the whole repository.
486     */
487    void rebuildReadAcls();
488
489    /**
490     * Gets the fulltext extracted from the binary fields.
491     *
492     * @since 5.9.3
493     */
494    Map<String, String> getBinaryFulltext(Serializable id);
495
496    /**
497     * Checks if change token management is enabled.
498     *
499     * @since 9.1
500     */
501    boolean isChangeTokenEnabled();
502
503    /**
504     * Marks the document as being modified by a user change.
505     * <p>
506     * This causes an additional change token increment and check during save.
507     *
508     * @param id the document id
509     * @since 9.2
510     */
511    void markUserChange(Serializable id);
512
513}