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