/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo MES
* Version: 1.4
*
* This file is part of Qcadoo.
*
* Qcadoo 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
* ***************************************************************************
*/
package com.qcadoo.mes.states.service.client;
import com.google.common.base.Preconditions;
import com.qcadoo.mes.states.StateChangeContext;
import com.qcadoo.mes.states.constants.StateChangeStatus;
import com.qcadoo.mes.states.exception.AnotherChangeInProgressException;
import com.qcadoo.mes.states.exception.StateChangeException;
import com.qcadoo.mes.states.exception.StateTransitionNotAlloweException;
import com.qcadoo.mes.states.service.StateChangeContextBuilder;
import com.qcadoo.mes.states.service.StateChangeService;
import com.qcadoo.mes.states.service.client.util.ViewContextHolder;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.Entity;
import com.qcadoo.view.api.ComponentState;
import com.qcadoo.view.api.ComponentState.MessageType;
import com.qcadoo.view.api.ViewDefinitionState;
import com.qcadoo.view.api.components.FormComponent;
import com.qcadoo.view.api.components.GridComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import static com.qcadoo.mes.states.constants.StateChangeStatus.*;
import static com.qcadoo.mes.states.messages.util.MessagesUtil.hasFailureMessages;
public abstract class AbstractStateChangeViewClient implements StateChangeViewClient {
private static final Logger LOG = LoggerFactory.getLogger(AbstractStateChangeViewClient.class);
@Autowired
private StateChangeContextBuilder stateChangeContextBuilder;
@Autowired
private StateChangeViewClientUtil viewClientUtil;
@Autowired
private StateChangeViewClientValidationUtil viewClientValidationUtil;
protected abstract StateChangeService getStateChangeService();
@Override
public final void changeState(final ViewDefinitionState view, final ComponentState component, final String[] args) {
final String newStateString = args[0];
Preconditions.checkNotNull(newStateString, "Missing target state argument!");
Preconditions.checkArgument(parseStateEnum(newStateString) != null, "Unsupported state value: " + newStateString);
changeState(buildViewContext(view, component), newStateString);
}
@Override
public final void changeState(final ViewContextHolder viewContext, final String targetState) {
final List<Entity> entities = viewClientUtil.getEntitiesFromComponent(viewContext);
for (Entity entity : entities) {
DataDefinition dd = entity.getDataDefinition();
Entity optionalMasterModel = dd.tryGetMasterModelEntity(entity.getId());
if (optionalMasterModel != null) {
entity = optionalMasterModel;
}
changeState(viewContext, targetState, entity);
optionalMasterModel = null;
entity = null;
}
}
@Override
public final void changeState(final ViewContextHolder viewContext, final String targetState, final Entity entity) {
try {
LOG.info(String.format("Change state. Entity name : %S id : %d. Target state : %S", entity.getDataDefinition().getName(),
entity.getId(), targetState));
StateChangeContext stateChangeContext = stateChangeContextBuilder.build(getStateChangeService()
.getChangeEntityDescriber(), entity, targetState);
getStateChangeService().changeState(stateChangeContext);
viewClientUtil.refreshComponent(viewContext);
showMessages(viewContext, stateChangeContext);
stateChangeContext = null;
} catch (AnotherChangeInProgressException e) {
viewContext.getMessagesConsumer().addMessage("states.messages.change.failure.anotherChangeInProgress",
MessageType.FAILURE);
LOG.info(String.format("Another state change in progress. Entity name : %S id : %d. Target state : %S",
entity.getDataDefinition().getName(), entity.getId(), targetState));
} catch (StateTransitionNotAlloweException e) {
viewContext.getMessagesConsumer().addMessage("states.messages.change.failure.transitionNotAllowed",
MessageType.FAILURE);
LOG.info(String.format("State change - transition not allowed. Entity name : %S id : %d. Target state : %S",
entity.getDataDefinition().getName(), entity.getId(), targetState));
} catch (Exception e) {
throw new StateChangeException(e);
}
}
@Override
public void showMessages(final ViewContextHolder viewContext, final StateChangeContext stateChangeContext) {
viewClientUtil.addStateMessagesToView(viewContext.getMessagesConsumer(), stateChangeContext);
viewClientValidationUtil.addValidationErrorMessages(viewContext.getMessagesConsumer(), stateChangeContext);
addFinalMessage(viewContext.getMessagesConsumer(), stateChangeContext);
}
private ViewContextHolder buildViewContext(final ViewDefinitionState view, final ComponentState component) {
if (component instanceof FormComponent) {
return new ViewContextHolder(view, component);
} else if (component instanceof GridComponent) {
return getViewContextHolderForListView(view, component);
} else {
throw new IllegalArgumentException("Unsupported view component " + component);
}
}
/**
* Returns {@link ViewContextHolder} for list (grid) view. Default messageConsumer is set to component which invoke event
* (usually grid component). Override this method if you want to change default consumer.
*
* @param view
* @param component
* @return
*/
protected ViewContextHolder getViewContextHolderForListView(final ViewDefinitionState view, final ComponentState component) {
return new ViewContextHolder(view, component);
}
protected final Object parseStateEnum(final String stateString) {
return getStateChangeService().getChangeEntityDescriber().parseStateEnum(stateString);
}
private void addFinalMessage(final ComponentState component, final StateChangeContext stateChangeContext) {
final StateChangeStatus status = stateChangeContext.getStatus();
if (SUCCESSFUL.equals(status)) {
component.addMessage("states.messages.change.successful", MessageType.SUCCESS);
} else if (PAUSED.equals(status)) {
component.addMessage("states.messages.change.paused", MessageType.INFO);
} else if (FAILURE.equals(status) && !hasFailureMessages(stateChangeContext.getAllMessages())) {
component.addMessage("states.messages.change.failure", MessageType.FAILURE);
} else if (CANCELED.equals(status)) {
component.addMessage("states.messages.change.canceled", MessageType.INFO);
}
}
}