/*
* Copyright 2011-2014 Conventions Framework.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*
*/
package org.conventionsframework.bean;
import org.conventionsframework.bean.state.State;
import org.conventionsframework.event.StatePullEvent;
import org.conventionsframework.event.StatePushEvent;
import org.conventionsframework.model.BaseEntity;
import org.conventionsframework.model.StateItem;
import org.conventionsframework.qualifier.BeanState;
import org.conventionsframework.qualifier.BeanStates;
import org.conventionsframework.qualifier.Config;
import org.conventionsframework.util.AnnotationUtils;
import java.io.Serializable;
import javax.enterprise.event.Event;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Instance;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
/**
*
* @author rmpestano Aug 13, 2011 10:50:42 AM
*
* Managed beans with the "power" of being tracked by the StatekController
* @see StateController
*/
public abstract class StateMBean<T extends BaseEntity> extends BaseMBean<T> implements Serializable {
@Inject
private Event<StatePushEvent> statePushEvent;
private BeanStates beanStates;
/**
* push this bean as an item in {@see StateController#stateItens}
*/
public void firePushStateEvent() {
if (beanStates != null) {//avoid unncessary looping
this.matchState(beanStates.value());
return;
}
BeanStates h = AnnotationUtils.findStatesAnnotation(getClass());
if (h != null) {
this.setStates(h);
this.matchState(h.value());
return;
} else {//only a state annotation is present
BeanState beanState = AnnotationUtils.findStateAnnotation(getClass());
if (beanState != null) {
if (beanState.beanState().equals(this.getBeanState().getStateName())) {
statePushEvent.fire(new StatePushEvent(new StateItem(beanState.outcome(), getEntity(), getBeanState(), beanState.value(), beanState.title(), this.getClass(), beanState.ajax(), beanState.callback(), beanState.update(),beanState.global(),beanState.resetValues(),beanState.immediate(),beanState.oncomplete(),beanState.addEntityIdParam())));
}
}
}
}
/**
* push this bean as an item in {@see StateController#stateItens}
*
*/
public void firePushStateEvent(State beanState) {
/**
* this method is fired by statePusher component and it is attached to
* preRenderView event which is fired by every ajax call, so to avoid
* this behavior we check if it is not a postback
*/
FacesContext context = facesContext.get();
if (!context.isPostback() && context.getExternalContext().getRequestParameterMap().get("pullState") == null && beanState != null) {//non ajaxCall
this.setBeanState(beanState);
if (beanStates != null) {//avoid unncessary looping
this.matchState(beanStates.value());
return;
}
BeanStates states = AnnotationUtils.findStatesAnnotation(getClass());
if (states != null) {
this.setStates(states);
this.matchState(states.value());
return;
} else {//only a state annotation is present
BeanState state = AnnotationUtils.findStateAnnotation(getClass());
if (states != null) {
if (state.beanState().equals(this.getBeanState().getStateName())) {
statePushEvent.fire(new StatePushEvent(new StateItem(state.outcome(), getEntity(), getBeanState(), state.value(), state.title(), this.getClass(), state.ajax(), state.callback(), state.update(),state.global(),state.resetValues(),state.immediate(),state.oncomplete(),state.addEntityIdParam())));
}
}
}
}
}
@Override
public String prepareInsert() {
setInsertState();
return super.prepareInsert();
}
@Override
public String prepareUpdate() {
setUpdateState();
return super.prepareUpdate();
}
public void onStackPull(@Observes StatePullEvent stackPullEvent) {
if (stackPullEvent.getStackItem().getInvokerClass().equals(this.getClass())) {
T entity = (T) stackPullEvent.getStackItem().getEntity();
this.setEntity(entity);
super.setBeanState(stackPullEvent.getStackItem().getBeanState());
this.afterItemPull();
}
}
@Override
public void resetEntity() {
super.resetEntity();
this.firePushStateEvent();
}
/**
* override this method if you want to perform any action when a stackitem is
* pulled
*
*/
public void afterItemPull() {
}
public BeanStates getBeanStates() {
return beanStates;
}
public void setStates(BeanStates beanStates) {
this.beanStates = beanStates;
}
private void matchState(BeanState[] value) {
for (BeanState beanState : value) {
if (beanState.beanState().equals(this.getBeanState().getStateName())) {
statePushEvent.fire(new StatePushEvent(new StateItem(beanState.outcome(), getEntity(), getBeanState(), beanState.value(), beanState.title(), this.getClass(), beanState.ajax(), beanState.callback(), beanState.update(),beanState.global(),beanState.resetValues(),beanState.immediate(),beanState.oncomplete(),beanState.addEntityIdParam())));
}
}
}
/**
* every time the state of the bean is changed
* push the bean to the top of {@see StateController#stateItens}
* @param beanState
*/
@Override
public void setBeanState(State beanState) {
if(!beanState.equals(this.getBeanState())){
super.setBeanState(beanState);
firePushStateEvent();
}
}
}