/* * Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de) * * Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://creativecommons.org/licenses/by-nc-sa/3.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. */ package de.knurt.fam.core.persistence.dao; import java.util.List; import java.util.Observable; import org.springframework.dao.DataIntegrityViolationException; import de.knurt.fam.core.model.persist.Storeable; /** * an abstract dao as base for all daos. provice the basic insert, update methods, but not a delete (which may not be wanted). * * @param <K> the main storable object the dao is resolving. there may exist other storables resolved by the dao. but every dao has a main type of * {@link Storeable} working with.<br /> * all other objects being resolved with this dao must depend from this main storable. e.g. the user dao also resolves mails stored for the * user. * @author Daniel Oltmanns * @since 0.20090412 */ public abstract class AbstractFamDao<K extends Storeable> extends Observable implements FamDao<K> { /** * return true, if the state of dataholder violates the data integrity. * * @param dataholder that shall be inserted or updated. * @param onInsert true, if dataholder shall be inserted. false, if it shall be updated. * @return true, if the state of dataholder violates the data integrity. */ protected abstract boolean isDataIntegrityViolation(K dataholder, boolean onInsert); /** * log an excpetion and throw it. * * @param dataholder the exception is thrown for * @throws DataIntegrityViolationException thrown because of given dataholder. */ protected abstract void logAndThrowDataIntegrityViolationException(K dataholder) throws DataIntegrityViolationException; /** * log that the given dataholder has been inserted into the database. * * @param dataholder the has been inserted. */ protected abstract void logInsert(K dataholder); /** * log that the given dataholder has been updated in the database. * * @param dataholder the has been updated. */ protected abstract void logUpdate(K dataholder); /** * set the id for the given dataholder. this assumes that every dataholder needs an id before it is written into the database. this is a method to * do that. note: there may exist no need for that if it is done by the database rule (as it is on autoincrement values on relational databases). * * @param dataholder the id is set to */ protected abstract void setIdToNextId(K dataholder); /** * {@inheritDoc} * * notify observers after successful insertion of the dataholder. */ @Override public synchronized boolean insert(K dataholder) throws DataIntegrityViolationException { boolean result = false; this.setIdToNextId(dataholder); if (this.isDataIntegrityViolation(dataholder, true)) { this.logAndThrowDataIntegrityViolationException(dataholder); } else { logInsert(dataholder); result = this.internInsert(dataholder); if (result) { setChanged(); dataholder.setJustBeenInserted(); notifyObservers(dataholder); } } return result; } /** * {@inheritDoc} * * notify observers before the dataholder is updated, even if updating fails. */ @Override public synchronized boolean update(K dataholder) throws DataIntegrityViolationException { boolean result = false; if (this.isDataIntegrityViolation(dataholder, false)) { this.logAndThrowDataIntegrityViolationException(dataholder); } else { logUpdate(dataholder); setChanged(); dataholder.setJustBeenUpdated(); notifyObservers(dataholder); result = this.internUpdate(dataholder); } return result; } /** * insert the given dataholder into the database. * * @param dataholder to store */ protected abstract boolean internInsert(K dataholder); /** * update the given dataholder into the database. * * @param dataholder to store */ protected abstract boolean internUpdate(K dataholder); /** * return first found object like example. or <code>null</code>, if no object like given stored * * @param example as example * @return first found object like example. */ @Override public K getOneLike(K example) { K result = null; List<K> examples = this.getObjectsLike(example); if (examples.size() > 0) { result = examples.get(0); } return result; } }