package act.db;
/*-
* #%L
* ACT Framework
* %%
* Copyright (C) 2014 - 2017 ActFramework
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
import act.Destroyable;
import act.app.AppContextAware;
import act.app.security.SecurityContextAware;
import java.util.Collection;
import java.util.List;
/**
* The Data Access Object interface
* @param <ID_TYPE> the generic key type
* @param <MODEL_TYPE> the generic model type
*/
public interface Dao<ID_TYPE, MODEL_TYPE, QUERY_TYPE extends Dao.Query<MODEL_TYPE, QUERY_TYPE>>
extends AppContextAware, SecurityContextAware, Destroyable {
/**
* Returns the identifier type
*/
Class<ID_TYPE> idType();
/**
* Returns the class of the Model entity this Dao operates on
*/
Class<MODEL_TYPE> modelType();
/**
* Returns the class of the bounded query type
*/
Class<QUERY_TYPE> queryType();
/**
* Find an entity by id, the primary key
* @param id the id to find the entity
* @return the entity found, or {@code null} if not found
*/
MODEL_TYPE findById(ID_TYPE id);
/**
* Find a collection of entities by fields and values.
* <p>The fields is specified in a {@code String} separated by any
* combination of the following separators</p>
* <ul>
* <li>comma: {@code ,}</li>
* <li>[space characters]</li>
* <li>semi colon: {@code ;}</li>
* <li>colon: {@code :}</li>
* </ul>
* <p>The values are specified in an object array. The number of values
* must match the number of fields specified. Otherwise {@link IllegalArgumentException}
* will be thrown out</p>
* <p>If entities found then they are returned in an {@link Iterable}. Otherwise
* an empty {@link Iterable} will be returned</p>
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @return A collection of entities in {@link Iterable}
* @throws IllegalArgumentException if fields number and value number doesn't match
*/
Iterable<MODEL_TYPE> findBy(String fields, Object... values) throws IllegalArgumentException;
/**
* Find one entity with fields and values specified.
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @return the entity matches or {@code null} if not found
* @throws IllegalArgumentException
* @see #findBy(String, Object...)
*/
MODEL_TYPE findOneBy(String fields, Object... values) throws IllegalArgumentException;
/**
* Find all entities from a give list of IDs. If there are certain ID in the list does not have
* an entity associated with then that ID will be ignored. The order of the returned iterator
* is not defined and shall be implemented as per specific implementation
* @param idList the ID list specifies the entities shall be returned
* @return a collection of entities
*/
Iterable<MODEL_TYPE> findByIdList(Collection<ID_TYPE> idList);
/**
* Find all entities of the collection/table specified by {@code MODEL_TYPE}
* @return all entities of the type bound to this Dao object in {@link Iterable}
*/
Iterable<MODEL_TYPE> findAll();
/**
* Find all entities of the collection/table specified by {@code MODEL_TYPE}
* @return all entities of the type bound to this Dao object in {@link List}
*/
List<MODEL_TYPE> findAllAsList();
/**
* Reload a model entity from persistent storage by it's {@link ModelBase#_id()}. This method
* returns the model been reloaded. Depending on the implementation, it could be the model
* passed in as parameter if it's mutable object or a fresh new object instance with the
* same ID as the model been passed in.
*
* @param entity the model to be reloaded
* @return a model been reloaded
*/
MODEL_TYPE reload(MODEL_TYPE entity);
/**
* Extract ID value from the give model entity
* @param entity the model entity object
* @return the ID of the entity
*/
ID_TYPE getId(MODEL_TYPE entity);
/**
* Returns total number of entities of the model type of this {@code Dao} object.
*/
long count();
/**
* Count the number of entities matches the fields and values specified. For the
* rule of fields and value specification, please refer to {@link #findBy(String, Object...)}
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @return the number of matched entities
* @throws IllegalArgumentException if fields number and value number doesn't match
*/
long countBy(String fields, Object ... values) throws IllegalArgumentException;
/**
* Save new or update existing the entity in persistent layer with all properties
* of the entity
* @param entity the entity to be saved or updated
* @return the entity that has been saved
*/
MODEL_TYPE save(MODEL_TYPE entity);
/**
* Update existing entity in persistent layer with specified fields and value. This allows
* partial updates of the entity to save the bandwidth.
* <p>Note the properties of the entity
* does not impact the update operation, however the {@link ModelBase#_id()} will be used to
* locate the record/document in the persistent layer corresponding to this entity.</p>
* <p>For fields and value specification rule, please refer to {@link #findBy(String, Object...)}</p>
* @param entity the entity
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
*/
void save(MODEL_TYPE entity, String fields, Object ... values);
/**
* Batch save entities
* @param entities an iterable to get entities to be saved
*/
List<MODEL_TYPE> save(Iterable<MODEL_TYPE> entities);
/**
* Remove the entity specified
* @param entity the entity to be removed
*/
void delete(MODEL_TYPE entity);
/**
* Remove entities specified by Query
* @param query the query specifies entities to be removed
*/
void delete(QUERY_TYPE query);
/**
* Remove entity by ID
* @param id the ID of the entity to be removed
*/
void deleteById(ID_TYPE id);
/**
* Delete a collection of entities by fields and values.
* <p>The fields is specified in a {@code String} separated by any
* combination of the following separators</p>
* <ul>
* <li>comma: {@code ,}</li>
* <li>[space characters]</li>
* <li>semi colon: {@code ;}</li>
* <li>colon: {@code :}</li>
* </ul>
* <p>The values are specified in an object array. The number of values
* must match the number of fields specified. Otherwise {@link IllegalArgumentException}
* will be thrown out</p>
* <p>If entities found then they are returned in an {@link Iterable}. Otherwise
* an empty {@link Iterable} will be returned</p>
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @throws IllegalArgumentException if fields number and value number doesn't match
*/
void deleteBy(String fields, Object... values) throws IllegalArgumentException;
/**
* Delete all entities in the table/collection inferred by this DAO
*/
void deleteAll();
/**
* Drop all entities (and optionally all indexes) from persistent storage
*/
void drop();
/**
* Return a {@link act.db.Dao.Query} bound to the {@code MODEL_TYPE}
* @return an new {@link Query} instance on this Dao
*/
QUERY_TYPE q();
/**
* Alias of {@link #q()}
* @return an new {@link Query} instance on this Dao
*/
QUERY_TYPE createQuery();
/**
* Return a {@link act.db.Dao.Query} bound to the {@code MODEL_TYPE} by fields and value arguments
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @return the query instance as described above
*/
QUERY_TYPE q(String fields, Object... values);
/**
* Alias of {@link #q(String, Object...)}
* @param fields the fields specification in {@code String}
* @param values the value array corresponding to the fields specification
* @return the query instance as described in {@link #q(String, Object...)}
*/
QUERY_TYPE createQuery(String fields, Object... values);
interface Query<MODEL_TYPE, QUERY_TYPE extends Query<MODEL_TYPE, QUERY_TYPE>> {
QUERY_TYPE offset(int pos);
QUERY_TYPE limit(int limit);
QUERY_TYPE orderBy(String ... fieldList);
MODEL_TYPE first();
Iterable<MODEL_TYPE> fetch();
long count();
}
}