/**
* ***************************************************************************
* 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.operationCostCalculations;
import static com.google.common.base.Preconditions.checkArgument;
import static com.qcadoo.mes.costNormsForOperation.constants.CostNormsForOperationConstants.MODEL_CALCULATION_OPERATION_COMPONENT;
import static com.qcadoo.mes.costNormsForOperation.constants.CostNormsForOperationConstants.PLUGIN_IDENTIFIER;
import static com.qcadoo.mes.technologies.constants.TechnologyFields.OPERATION_COMPONENTS;
import static java.util.Arrays.asList;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.qcadoo.mes.technologies.constants.TechnologiesConstants;
import com.qcadoo.model.api.DataDefinition;
import com.qcadoo.model.api.DataDefinitionService;
import com.qcadoo.model.api.Entity;
import com.qcadoo.model.api.EntityTree;
import com.qcadoo.model.api.EntityTreeNode;
@Service
public class OperationCostCalculationTreeBuilder {
private static final String L_TECHNOLOGY = "technology";
private static final String L_ORDER = "order";
private static final String L_OPERATION = "operation";
private static final String L_ENTITY_TYPE = "entityType";
private static final String L_PRODUCTION_IN_ONE_CYCLE = "productionInOneCycle";
private static final String L_TECHNOLOGY_OPERATION_COMPONENT = "technologyOperationComponent";
private static final String L_CALCULATION_OPERATION_COMPONENTS = "calculationOperationComponents";
private static final Logger LOG = LoggerFactory.getLogger(OperationCostCalculationTreeBuilder.class);
@Autowired
private DataDefinitionService dataDefinitionService;
@Transactional
public Entity copyTechnologyTree(final Entity costCalculation) {
deleteOperationsTreeIfExists(costCalculation);
Entity operationsTreeContainer;
if (costCalculation.getBelongsToField(L_ORDER) == null) {
operationsTreeContainer = costCalculation.getBelongsToField(L_TECHNOLOGY);
} else {
operationsTreeContainer = costCalculation.getBelongsToField(L_ORDER).getBelongsToField(L_TECHNOLOGY);
}
EntityTree sourceOperationsTree = operationsTreeContainer.getTreeField(OPERATION_COMPONENTS);
return createTechnologyInstanceForCalculation(sourceOperationsTree, costCalculation);
}
private Entity createTechnologyInstanceForCalculation(final EntityTree sourceTree, final Entity parentEntity) {
checkArgument(sourceTree != null, "source is null");
DataDefinition calculationOperationComponentDD = dataDefinitionService.get(PLUGIN_IDENTIFIER,
MODEL_CALCULATION_OPERATION_COMPONENT);
// drop old operation components tree
EntityTree oldCalculationOperationComponents = parentEntity.getTreeField(L_CALCULATION_OPERATION_COMPONENTS);
if (oldCalculationOperationComponents != null && oldCalculationOperationComponents.getRoot() != null) {
calculationOperationComponentDD.delete(oldCalculationOperationComponents.getRoot().getId());
}
Entity tree = createCalculationOperationComponent(sourceTree.getRoot(), null, calculationOperationComponentDD,
parentEntity);
parentEntity.setField(L_CALCULATION_OPERATION_COMPONENTS, asList(tree));
return parentEntity;
}
private Entity createCalculationOperationComponent(final EntityTreeNode sourceTreeNode, final Entity parent,
final DataDefinition calculationOperationComponentDD, final Entity parentEntity) {
Entity calculationOperationComponent = calculationOperationComponentDD.create();
calculationOperationComponent.setField("parent", parent);
calculationOperationComponent.setField(parentEntity.getDataDefinition().getName(), parentEntity);
// FIXME MAKU ask ALBR about strategy for reference technology pointers.
if (L_OPERATION.equals(sourceTreeNode.getField(L_ENTITY_TYPE))) {
createOrCopyCalculationOperationComponent(sourceTreeNode, calculationOperationComponent, parentEntity);
} else {
Entity referenceTechnology = sourceTreeNode.getBelongsToField("referenceTechnology");
createOrCopyCalculationOperationComponent(referenceTechnology.getTreeField("operationComponents").getRoot(),
calculationOperationComponent, parentEntity);
}
return calculationOperationComponent;
}
private void createOrCopyCalculationOperationComponent(final EntityTreeNode operationComponent,
final Entity calculationOperationComponent, final Entity costCalculation) {
DataDefinition sourceDD = operationComponent.getDataDefinition();
for (String fieldName : Arrays.asList("priority", "nodeNumber", L_PRODUCTION_IN_ONE_CYCLE,
"nextOperationAfterProducedQuantity", "operationOffSet", "effectiveOperationRealizationTime",
"effectiveDateFrom", "effectiveDateTo", "pieceworkCost", "numberOfOperations")) {
calculationOperationComponent.setField(fieldName, operationComponent.getField(fieldName));
}
calculationOperationComponent.setField(L_OPERATION, operationComponent.getBelongsToField(L_OPERATION));
calculationOperationComponent.setField(
"nextOperationAfterProducedType",
operationComponent.getField("nextOperationAfterProducedType") == null ? "01all" : operationComponent
.getField("nextOperationAfterProducedType"));
if (!TechnologiesConstants.MODEL_TECHNOLOGY_OPERATION_COMPONENT.equals(sourceDD.getName())) {
LOG.error("incorrect model!");
}
calculationOperationComponent.setField(L_TECHNOLOGY_OPERATION_COMPONENT, operationComponent);
calculationOperationComponent.setField(L_ENTITY_TYPE, L_OPERATION);
List<Entity> newTechnologyInstanceOperationComponents = new ArrayList<Entity>();
for (EntityTreeNode child : operationComponent.getChildren()) {
newTechnologyInstanceOperationComponents.add(createCalculationOperationComponent(child,
calculationOperationComponent, calculationOperationComponent.getDataDefinition(), costCalculation));
}
calculationOperationComponent.setField("children", newTechnologyInstanceOperationComponents);
}
private void deleteOperationsTreeIfExists(final Entity costCalculation) {
Entity yetAnotherCostCalculation = costCalculation.getDataDefinition().get(costCalculation.getId());
EntityTree existingOperationsTree = yetAnotherCostCalculation.getTreeField(L_CALCULATION_OPERATION_COMPONENTS);
if (existingOperationsTree == null || existingOperationsTree.getRoot() == null) {
return;
}
debug("existing calculation operation components tree will be removed..");
EntityTreeNode existingOperationsTreeRoot = existingOperationsTree.getRoot();
existingOperationsTreeRoot.getDataDefinition().delete(existingOperationsTreeRoot.getId());
}
private void debug(final String message) {
if (LOG.isDebugEnabled()) {
LOG.debug(message);
}
}
}