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