001/*
002 * (C) Copyright 2014-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.dbs;
020
021import java.io.Serializable;
022import java.util.Collection;
023import java.util.List;
024import java.util.Map;
025import java.util.Set;
026import java.util.stream.Stream;
027
028import org.nuxeo.ecm.core.api.PartialList;
029import org.nuxeo.ecm.core.api.ScrollResult;
030import org.nuxeo.ecm.core.api.repository.FulltextConfiguration;
031import org.nuxeo.ecm.core.blob.BlobManager;
032import org.nuxeo.ecm.core.model.LockManager;
033import org.nuxeo.ecm.core.model.Repository;
034import org.nuxeo.ecm.core.query.sql.model.OrderByClause;
035import org.nuxeo.ecm.core.storage.State;
036import org.nuxeo.ecm.core.storage.State.StateDiff;
037import org.nuxeo.ecm.core.storage.dbs.DBSTransactionState.ChangeTokenUpdater;
038
039/**
040 * Interface for a {@link Repository} for Document-Based Storage.
041 *
042 * @since 5.9.4
043 */
044public interface DBSRepository extends Repository, LockManager {
045
046    /**
047     * Gets the blob manager.
048     *
049     * @return the blob manager.
050     */
051    BlobManager getBlobManager();
052
053    /**
054     * Checks if fulltext indexing (and search) is disabled.
055     *
056     * @return {@code true} if fulltext indexing is disabled, {@code false} if it is enabled
057     * @since 7.1, 6.0-HF02
058     */
059    boolean isFulltextDisabled();
060
061    /**
062     * Checks if fulltext search is disabled.
063     *
064     * @return {@code true} if fulltext search is disabled, {@code false} if it is enabled
065     * @since 10.2
066     */
067    boolean isFulltextSearchDisabled();
068
069
070    /**
071     * Checks if database-managed document change tokens are enabled.
072     *
073     * @return {@code true} if the database maintains document change tokens
074     * @since 9.1
075     */
076    boolean isChangeTokenEnabled();
077
078    /**
079     * Gets the root id.
080     *
081     * @return the root id.
082     */
083    String getRootId();
084
085    /**
086     * Generates a new id for a document.
087     *
088     * @return the new id
089     */
090    String generateNewId();
091
092    /**
093     * Reads the state of a document.
094     *
095     * @param id the document id
096     * @return the document state, or {@code null} if not found
097     */
098    State readState(String id);
099
100    /**
101     * Reads the partial state of a document.
102     *
103     * @param id the document id
104     * @param keys the keys to read
105     * @return the document partial state, or {@code null} if not found
106     * @since 9.10
107     */
108    default State readPartialState(String id, Collection<String> keys) {
109        // overrides should optimize to only return the required keys and nothing more
110        return readState(id);
111    }
112
113    /**
114     * Reads the states of several documents.
115     * <p>
116     * The returned states may be in a different order than the ids.
117     *
118     * @param ids the document ids
119     * @return the document states, an element by be {@code null} if not found
120     */
121    List<State> readStates(List<String> ids);
122
123    /**
124     * Creates a document.
125     *
126     * @param state the document state
127     */
128    void createState(State state);
129
130    /**
131     * Creates documents.
132     *
133     * @param states the document states
134     */
135    default void createStates(List<State> states) {
136        states.forEach(this::createState);
137    }
138
139    /**
140     * Updates a document.
141     *
142     * @param id the document id
143     * @param diff the diff to apply
144     * @param changeTokenUpdater how to get and update the change token (may be {@code null})
145     */
146    void updateState(String id, StateDiff diff, ChangeTokenUpdater changeTokenUpdater);
147
148    /**
149     * Deletes a set of document.
150     *
151     * @param ids the document ids
152     */
153    void deleteStates(Set<String> ids);
154
155    /**
156     * Reads the state of a child document.
157     *
158     * @param parentId the parent document id
159     * @param name the name of the child
160     * @param ignored a set of document ids that should not be considered
161     * @return the state of the child document, or {@code null} if not found
162     */
163    State readChildState(String parentId, String name, Set<String> ignored);
164
165    /**
166     * Checks if a document has a child with the given name
167     *
168     * @param parentId the parent document id
169     * @param name the name of the child
170     * @param ignored a set of document ids that should not be considered
171     * @return {@code true} if the child exists, {@code false} if not
172     */
173    boolean hasChild(String parentId, String name, Set<String> ignored);
174
175    /**
176     * Queries the repository for documents having key = value.
177     *
178     * @param key the key
179     * @param value the value
180     * @param ignored a set of document ids that should not be considered
181     * @return the document states matching the query
182     */
183    List<State> queryKeyValue(String key, Object value, Set<String> ignored);
184
185    /**
186     * Queries the repository for documents having key1 = value1 and key2 = value2.
187     *
188     * @param key1 the first key
189     * @param value1 the first value
190     * @param key2 the second key
191     * @param value2 the second value
192     * @param ignored a set of document ids that should not be considered
193     * @return the document states matching the query
194     */
195    List<State> queryKeyValue(String key1, Object value1, String key2, Object value2, Set<String> ignored);
196
197    /**
198     * Returns a stream of descendants from a given root document, in no particular order. This does not include
199     * information about the root document itself.
200     * <p>
201     * THE STREAM MUST BE CLOSED WHEN DONE to release resources.
202     *
203     * @param id the root document id
204     * @param keys what to collect about the descendants in addition to their ids
205     * @return a stream of {@link State}s; THE STREAM MUST BE CLOSED WHEN DONE
206     * @since 9.3
207     */
208    Stream<State> getDescendants(String id, Set<String> keys);
209
210    /**
211     * Returns a stream of descendants from a given root document, in no particular order. This does not include
212     * information about the root document itself.
213     * <p>
214     * THE STREAM MUST BE CLOSED WHEN DONE to release resources.
215     *
216     * @param id the root document id
217     * @param keys what to collect about the descendants in addition to their ids
218     * @param limit the maximum number of descendants to return
219     * @return a stream of {@link State}s; THE STREAM MUST BE CLOSED WHEN DONE
220     * @since 9.10
221     */
222    default Stream<State> getDescendants(String id, Set<String> keys, int limit) {
223        // limit unused by default, override for a more efficient implementation
224        return getDescendants(id, keys);
225    }
226
227    /**
228     * Queries the repository to check if there are documents having key = value.
229     *
230     * @param key the key
231     * @param value the value
232     * @param ignored a set of document ids that should not be considered
233     * @return {@code true} if the query matches at least one document, {@code false} if the query matches nothing
234     */
235    boolean queryKeyValuePresence(String key, String value, Set<String> ignored);
236
237    /**
238     * Queries the repository for documents matching a NXQL query, and returns a projection of the documents.
239     *
240     * @param evaluator the map-based evaluator for the query
241     * @param orderByClause an ORDER BY clause
242     * @param distinctDocuments {@code true} if the projection should return a maximum of one row per document
243     * @param limit the limit on the number of documents to return
244     * @param offset the offset in the list of documents to return
245     * @param countUpTo if {@code -1}, count the total size without offset/limit.<br>
246     *            If {@code 0}, don't count the total size, set it to {@code -1} .<br>
247     *            If {@code n}, count the total number if there are less than n documents otherwise set the total size
248     *            to {@code -2}.
249     * @return a partial list of maps containing the NXQL projections requested, and the total size according to
250     *         countUpTo
251     */
252    PartialList<Map<String, Serializable>> queryAndFetch(DBSExpressionEvaluator evaluator, OrderByClause orderByClause,
253            boolean distinctDocuments, int limit, int offset, int countUpTo);
254
255    /**
256     * Gets the lock manager for this repository.
257     *
258     * @return the lock manager
259     * @since 7.4
260     */
261    LockManager getLockManager();
262
263    /**
264     * Executes the given query and returns the first batch of results containing id of documents, next batch must be
265     * requested within the {@code keepAliveSeconds} delay.
266     *
267     * @since 8.4
268     */
269    ScrollResult<String> scroll(DBSExpressionEvaluator evaluator, int batchSize, int keepAliveSeconds);
270
271    /**
272     * Get the next batch of results containing id of documents, the {@code scrollId} is part of the previous
273     * {@link ScrollResult} response.
274     *
275     * @since 8.4
276     */
277    ScrollResult<String> scroll(String scrollId);
278
279    /**
280     * Called when created a transaction.
281     *
282     * @since 8.10
283     */
284    default void begin() {
285
286    }
287
288    /**
289     * Saves and flushes to database.
290     *
291     * @since 8.10
292     */
293    default void commit() {
294
295    }
296
297    /**
298     * Rolls back the save state by applying the undo log.
299     *
300     * @since 8.10
301     */
302    default void rollback() {
303
304    }
305
306}