/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.business.common.daos;
import java.io.Serializable;
import java.util.List;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.springframework.dao.OptimisticLockingFailureException;
/**
* The interface all DAOs (Data Access Objects) must implement.
* In general, a DAO must be implemented for each persistent entity.
* Concrete DAOs may provide (and usually will provide) additional methods.
*
* @author Fernando Bellas Permuy <fbellas@udc.es>
*
* @param <E> Entity class
* @param <PK> Primary key class
*/
public interface IGenericDAO <E, PK extends Serializable>{
Class<E> getEntityClass();
/**
* It inserts the object passed as a parameter in the ORM session,
* planning it for updating (even though it is not modified before or after the call to this method)
* or insertion, depending if it is was detached or transient.
*
* If another instance with the same key already exists in the ORM session, an exception is thrown.
* When updating, version check is executed
* (if the entity has version control enabled) with
* the possible <code>org.springframework.dao.OptimisticLockingFailureException</code> being thrown.
*
* @throws ValidationException
* if the entity has some invalid values
*/
void save(E entity) throws ValidationException;
/**
* Unlike <code>save</code>, it does not execute validations.
*/
void saveWithoutValidating(E entity);
/**
* It reattaches the entity to the current session.
* This method bypasses hibernate validations and must only be used on read only
* transaction {@link OptimisticLockingFailureException} can be thrown if the entity has
* been updated for another transaction.
* @param entity
*/
void reattach(E entity);
/**
* It inserts the object passed as a parameter in the ORM session.
*
* Unlike <code>save</code>, the entity passed as a parameter must not have been modified,
* and after calling the method, the entity is not considered dirty
* (but it will be considered dirty if it is modified after calling the method).
*
* Like <code>save</code>, if another instance with the same key already exists in the ORM session,
* an exception is thrown.
* <p/>
* The intended use of the method is for reattachment of detached objects which have not been modified
* before calling this method and will not be modified during the transaction.
*/
void reattachUnmodifiedEntity(E entity);
/**
* It merges an entity.
*
* The caller must discard the reference passed as a parameter and work with the returned reference.
* Merging is analternative technique to reattachment with <code>save</code>,
* which must be used when it cannot be assessed another instance with the same identifier
* as the one passed as a parameter already exists in the underlying ORM session.
*
* Like <code>save</code>, version check is executed when updating.
* <p/>
* Since the caller must discard the reference passed as a parameter and work with the returned reference,
* merging is a technique more complicated than reattachment.
* Reattachment (by using <code>save</code> and/or <code>reattachUnmodifiedEntity</code>)
* should be the preferred technique.
*
* @param entity
*/
E merge(E entity);
/**
* It checks if the version of the instance passed as a parameter is equal to the one in the database.
*
* The instance must have methods conforming to the following signatures:
* <code>java.io.Serializable getId()</code> (to get the key) and <code>[long|Long] getVersion()</code>
* (to get the version).
* <br/>
* If the check is not passed,
* <code>org.springframework.dao.OptimisticLockingFailureException</code> is thrown.
*
* If the key or the version of the entity is <code>null</code>, or the entity does not exist in database,
* the check is considered to be successful.
*
* This lets client code to treat creation and modification of instances in a unified way.
*/
void checkVersion(E entity);
/**
* It sets a WRITE lock on the instance passed as a parameter, causing the same kind of reattachment
* as <code>reattachUnmodifiedEntity</code>.
*
* Other concurrent transactions will be blocked if they try to write or set a WRITE lock
* (but they can read) on the same persistent instance.
*
* If the version field is not equal to the one in the database,
* <code>org.springframework.dao.OptimisticLockingFailureException</code> is thrown.
* The lock is released when the transaction finishes.
* <p/>
* The intended use of this method is to enable pessimistic locking when
* the version check mechanism is not enough for controlling concurrent access.
*
* Most concurrent cases can be automatically managed with the usual version check mechanism.
*/
void lock(E entity);
E find(PK id) throws InstanceNotFoundException;
/**
* Unlike <code>find(PK)</code>, it returns a runtime exception if the entity does not exist.
* So, this method should be used when the entity with the key passed as a parameter is supposed to exist.
*/
E findExistingEntity(PK id);
boolean exists(PK id);
void remove(PK id) throws InstanceNotFoundException;
<T extends E> List<T> list(Class<T> klass);
void flush();
}