// ========================================================================
// Copyright (C) zeroth Project Team. All rights reserved.
// GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007
// http://www.gnu.org/licenses/agpl-3.0.txt
// ========================================================================
package zeroth.framework.screen.iface.jsf;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Map.Entry;
import javax.ejb.EJBException;
import javax.enterprise.context.Conversation;
import javax.faces.application.FacesMessage;
import javax.inject.Inject;
import org.apache.commons.lang3.Validate;
import zeroth.framework.enterprise.app.SimpleRepositoryApplication;
import zeroth.framework.enterprise.domain.ConstraintsException;
import zeroth.framework.enterprise.shared.EnterpriseRuntimeException;
import zeroth.framework.enterprise.shared.Persistable;
/**
* JSFアクション
* @param <E> エンティティ型
* @param <ID> 識別子オブジェクト型
* @param <F> 検索条件オブジェクト型 TODO extends ValueObject<?>
* @author nilcy
*/
public abstract class AbstractActionImpl<E extends Persistable<ID>, ID extends Serializable, F extends Serializable>
implements SimpleAction<E, ID, F> {
/** 製品番号 */
private static final long serialVersionUID = -8034832957766744039L;
/** ページサイズ */
private static final int PAGE_SIZE = 10;
/** 永続エラーのキー */
private static final String KEY_PERSISTENCE_ERROR = "PersistenceErrorOccured";
/** 選択オブジェクト */
private E selected;
/** 検索条件 */
private F filter;
/** エンティティ集合 */
private Collection<E> items;
/** ページ条件 */
private Pagination<E> pagination;
/** 識別子 */
private ID id;
/** 現在ページ */
private int page;
/** 会話オブジェクト */
@Inject
private Conversation conversation;
/** コンストラクタ */
public AbstractActionImpl() {
}
/** {@inheritDoc} */
@Override
public Collection<E> getItems() {
if (this.items == null) {
// this.items = getApplication().findMany(getFilter());
this.items = getPagination().createCollection();
}
return this.items;
}
/** {@inheritDoc} */
@Override
public E getSelected() {
if (this.selected == null) {
this.selected = this.id == null ? this.createInstance() : this.loadInstance();
}
return this.selected;
}
/** {@inheritDoc} */
@Override
public void refresh() {
this.items = null;
pagination = null;
return;
}
/** {@inheritDoc} */
@Override
public void beginConversation() {
if (this.conversation.isTransient()) {
this.conversation.setTimeout(FacesProfile.CONVERSATION_TIMEOUT);
this.conversation.begin();
}
}
/** {@inheritDoc} */
@Override
public void endConversation() {
if (!this.conversation.isTransient()) {
this.conversation.end();
}
}
/** {@inheritDoc} */
@Override
public boolean isManaged() {
return this.getSelected().isPersisted();
}
/** {@inheritDoc} */
@Override
public String save() {
String outcome = null;
try {
if (this.beforeSave()) {
final String key = !this.selected.isPersisted() ? "EntityCreated" : "EntityUpdated";
this.selected = getApplication().save(this.selected);
this.endConversation();
FacesHelper.addSuccessMessage(FacesHelper.getBundleMessage(key));
FacesHelper.keepMessage();
FacesHelper.getFlash().put("id", this.selected.identity());
outcome = "saved";
}
} catch (final ConstraintsException e) {
for (final Entry<String, Object[]> entry : e.getCauseMap().entrySet()) {
FacesHelper.addFacesMessage(
FacesMessage.SEVERITY_ERROR,
MessageFormat.format(FacesHelper.getBundleMessage(entry.getKey()),
entry.getValue()));
}
FacesHelper.getCurrentInstance().validationFailed();
} catch (final EJBException e) {
FacesHelper.addFacesMessage(FacesMessage.SEVERITY_FATAL,
FacesHelper.getBundleMessage(KEY_PERSISTENCE_ERROR));
}
return outcome;
}
/** {@inheritDoc} */
@Override
public String delete() {
String outcome = null;
try {
Validate.notNull(this.getId());
this.selected = getApplication().find(this.getId());
getApplication().delete(this.selected);
this.endConversation();
FacesHelper.addSuccessMessage(FacesHelper.getBundleMessage("EntityDeleted"));
FacesHelper.keepMessage();
outcome = "deleted";
} catch (final ConstraintsException e) {
for (final Entry<String, Object[]> entry : e.getCauseMap().entrySet()) {
FacesHelper.addFacesMessage(
FacesMessage.SEVERITY_ERROR,
MessageFormat.format(FacesHelper.getBundleMessage(entry.getKey()),
entry.getValue()));
}
} catch (final EJBException e) {
FacesHelper.addFacesMessage(FacesMessage.SEVERITY_FATAL,
FacesHelper.getBundleMessage(KEY_PERSISTENCE_ERROR));
}
return outcome;
}
/** {@inheritDoc} */
@Override
public String cancel() {
this.endConversation();
return "cancelled";
}
/** {@inheritDoc} */
@Override
public Pagination<E> getPagination() {
if (pagination == null) {
pagination = new AbstractPagination<E>(PAGE_SIZE, this.page) {
/** 項目の件数 */
private int itemsCount;
@Override
public Collection<E> createCollection() {
final Collection<E> results = AbstractActionImpl.this.getApplication()
.findMany(getFilter());
itemsCount = (int) AbstractActionImpl.this.getApplication().count(getFilter());
return results;
}
@Override
public int getItemsCount() {
return itemsCount;
}
};
}
return pagination;
}
/** {@inheritDoc} */
@Override
public abstract SimpleRepositoryApplication<E, ID, F> getApplication();
/**
* インスタンスのロード
* @return インスタンス
*/
protected E loadInstance() {
Validate.notNull(this.getId());
return getApplication().find(this.getId());
}
/**
* エンティティの作成
* @return エンティティ
*/
@SuppressWarnings("unchecked")
protected E createInstance() {
try {
return ((Class<E>) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0]).newInstance();
} catch (final InstantiationException e) {
throw new EnterpriseRuntimeException(e);
} catch (final IllegalAccessException e) {
throw new EnterpriseRuntimeException(e);
}
}
/**
* 検索条件の作成
* @return 検索条件
*/
protected abstract F createFilter();
// /**
// * 検索条件の作成
// * @return 検索条件
// */
// @SuppressWarnings("unchecked")
// protected F createRestriction() {
// try {
// return ((Class<F>) ((ParameterizedType) this.getClass().getGenericSuperclass())
// .getActualTypeArguments()[2]).newInstance();
// } catch (final InstantiationException e) {
// throw new EnterpriseRuntimeException(e);
// } catch (final IllegalAccessException e) {
// throw new EnterpriseRuntimeException(e);
// }
// }
/** {@inheritDoc} */
@Override
public F getFilter() {
if (this.filter == null) {
this.filter = this.createFilter();
}
return this.filter;
}
/**
* 保存前の処理
* @return 成否
*/
@SuppressWarnings("static-method")
protected boolean beforeSave() {
return true;
}
/** {@inheritDoc} */
@Override
public ID getId() {
return this.id;
}
/** {@inheritDoc} */
@Override
public void setId(final ID aId) {
this.id = aId;
}
/** {@inheritDoc} */
@Override
public int getPage() {
return this.page;
}
/** {@inheritDoc} */
@Override
public void setPage(final int aPage) {
this.page = aPage;
}
}