/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package framework.beans.directory;
import framework.beans.HardCodedIDs;
import framework.beans.SecuredBean;
import framework.beans.security.BeanRights;
import java.util.ArrayList;
import java.util.List;
import framework.generic.ClipsServerException;
import framework.generic.EDataIntegrity;
import framework.generic.ENotMoveToTrash;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import framework.security.RightChecker;
import framework.security.UserRight;
import javax.ejb.EJBException;
/**
* @param <DEN>
* @param <DETAILSTYPE>
* @security ok
* @author axe
*/
abstract public class DirectoryBean<DEN extends DirectoryEntity<DETAILSTYPE>, DETAILSTYPE extends DirectoryItemDetails> extends SecuredBean
implements DirectoryBeanRemote<DETAILSTYPE> {
public final static int REMOVE = 0;
public final static int TRASHE = 1;
public final static char HIDE_SYMBOL = '*';
protected Class<? extends DEN> entityClass;
protected String hudClassName;
/**
* Право для добавления нового элемента в справочник
*/
protected abstract UserRight getRightForCreateDirectoryItem() throws ClipsServerException;
/**
* Право для изменения и удаления элемента справочника
*/
protected abstract UserRight getRightForWriteToDirectory() throws ClipsServerException;
public static int COMMAND_CREATE = 0;
public static int COMMAND_WRITE = 1;
@Override
protected void initBeanRights() throws ClipsServerException {
int [] r = new int[2];
r[COMMAND_CREATE] = getRightForCreateDirectoryItem() == null
? -1 : RightPresence(getRightForCreateDirectoryItem().id);
//Если справочник захардкожен его нельзя изменять
if (!HardCodedIDs.canModify(entityClass, 0)) {
r[COMMAND_CREATE] = getRightForCreateDirectoryItem() == null
? -1 : -getRightForCreateDirectoryItem().id;
}
r[COMMAND_WRITE] = getRightForWriteToDirectory() == null
? -1 : RightPresence(getRightForWriteToDirectory().id);
rights = new BeanRights(r);
}
protected DirectoryBean(Class<? extends DEN> enityClass, String hudClassName) {
this.entityClass = enityClass;
this.hudClassName = hudClassName;
}
public Class<? extends DEN> getEntityClass() {
return entityClass;
}
/**
*
* @return
* @security нет ограничений
*/
@Override
public List<DETAILSTYPE> getDirectory() {
try {
Query query = manager.createQuery("SELECT a FROM "
+ entityClass.getSimpleName() + " a ORDER BY a.id ASC");
@SuppressWarnings("unchecked")
List<DEN> res = query.getResultList();
ArrayList <DETAILSTYPE> det = new ArrayList<DETAILSTYPE>(res.size());
for(int i=0; i<res.size(); i++) {
det.add(res.get(i).getDetails((RightChecker) this));
}
return det;
} catch (NoResultException ex) {
return new ArrayList<DETAILSTYPE>();
}
}
/**
* обновляет элемент справочника
* @param item элемент справочника
* @throws ClipsServerException
*/
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
final public void update(DETAILSTYPE item) throws ClipsServerException {
checkCommandAccessibility(COMMAND_WRITE);
item.title = item.title.trim();
checkUniqe(item);
checkTitleValid(item.title);
DEN entity = findEntity(entityClass, item.id, hudClassName);
if (!HardCodedIDs.canModify(entityClass, entity.getId())) {
throw new ClipsServerException("Запрещено изменять элемент справочника " + hudClassName + " cо значением: " + entity.getTitle());
}
onUpdate(entity, item);
set(entity, item);
manager.persist(entity);
manager.flush();
manager.refresh(entity);
afterUpdate(entity);
}
/**
* удаляет элемент справочника
* @param id идентификатор элемента справочника
* @throws ClipsServerException
* @return 0 - удален, 1 - удален в корзину
*/
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
final public int remove(int id) throws ClipsServerException {
checkCommandAccessibility(COMMAND_WRITE);
DEN entity = findEntity(entityClass, id, hudClassName);
if (!HardCodedIDs.canRemove(entityClass, entity.getId())) {
throw new ClipsServerException("Запрещено удалять элемент справочника: " + hudClassName + " cо значением: " + entity.getTitle());
}
try {
onRemove(entity);
manager.remove(entity);
manager.flush();
return REMOVE;
} catch (ENotMoveToTrash ex) {
throw ex;
} catch(EJBException ex) {
if (!(entity instanceof DirectoryEntityTrash)) {
throw ex;
}
((DirectoryEntityTrash)entity).setTrash(true);
manager.merge(entity);
return TRASHE;
} catch(EDataIntegrity ex) {
if (!(entity instanceof DirectoryEntityTrash)) {
throw ex;
}
((DirectoryEntityTrash)entity).setTrash(true);
manager.merge(entity);
return TRASHE;
}
}
/**
* Добавляет новый элемент справочника
* @param item новый элемент справочника
* @return
* @throws ClipsServerException
*/
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Override
final public DETAILSTYPE append(DETAILSTYPE item) throws ClipsServerException {
checkCommandAccessibility(COMMAND_CREATE);
if (!HardCodedIDs.canModify(entityClass, 0)) {
throw new ClipsServerException("Запрещено добавлять элементы в справочник " + hudClassName);
}
item.title = item.title.trim();
checkUniqe(item);
try {
item.id = 0;
checkTitleValid(item.title);
onAppend(item);
DEN entity = entityClass.newInstance();
set(entity, item);
manager.persist(entity);
manager.flush();
manager.refresh(entity);
return entity.getDetails((RightChecker) this);
} catch(InstantiationException ex) {
throw new ClipsServerException("Не удалось создать класс строки таблицы '"
+ hudClassName + "'", ex);
} catch(IllegalAccessException ex) {
throw new ClipsServerException("Не удалось получить доступ к классу строки таблицы '"
+ hudClassName + "'", ex);
}
}
protected abstract void set(DEN entity, DETAILSTYPE details)
throws ClipsServerException;
/**
* Вызывается перед созданием нового итема
* @param details детали, из которой будет создана сущность
* @throws ClipsServerException при выбросе исключения добавление отменяется
*/
protected void onAppend(DETAILSTYPE details)
throws ClipsServerException {}
/**
* Вызывается перед изменением итема
* @param entity сущность итема
* @param details детали, на основе которых будет изменена сущность
* @throws ClipsServerException при выбросе исключения изменения отменяются
*/
protected void onUpdate(DEN entity, DETAILSTYPE details)
throws ClipsServerException {}
protected void afterUpdate(DEN entity)
throws ClipsServerException {}
/**
* Вызывается перед удалением итема
* @param entity
* @throws ClipsServerException при выбросе исключения удаление отменяется
*/
protected void onRemove(DEN entity) throws ClipsServerException {}
/**
* Проверка названия на корректность
* Если проверка не пройдена - вылетит ошибка
* @param title название с отрезанными пробелами
* @throws ClipsServerException
*/
protected void checkTitleValid(String title) throws ClipsServerException {
if (title == null || title.isEmpty()) {
throw new EDataIntegrity("Название не задано");
}
if (title.charAt(0) == HIDE_SYMBOL){
throw new EDataIntegrity("Название не может начинаться с символа \""
+ HIDE_SYMBOL + "\"");
}
}
/**
* if item with specified title be in DB function must throw exeption
* @param item
* @throws ClipsServerException
*/
protected void checkUniqe(DETAILSTYPE item) throws ClipsServerException {}
}