<commit_before>/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolóxico de Galicia
 * Copyright (C) 2010-2011 Igalia, S.L.
 *
 * This program 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, see <http://www.gnu.org/licenses/>.
 */

package org.libreplan.ws.subcontract.impl;

import static org.libreplan.web.I18nHelper._;

import java.util.Arrays;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.hibernate.NonUniqueResultException;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.daos.IEntitySequenceDAO;
import org.libreplan.business.common.entities.EntityNameEnum;
import org.libreplan.business.common.entities.EntitySequence;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.orders.entities.TaskSource.IOptionalPersistence;
import org.libreplan.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.libreplan.business.planner.daos.ITaskSourceDAO;
import org.libreplan.business.scenarios.daos.IScenarioDAO;
import org.libreplan.business.scenarios.entities.OrderVersion;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.ws.common.api.InstanceConstraintViolationsDTO;
import org.libreplan.ws.common.api.InstanceConstraintViolationsDTOId;
import org.libreplan.ws.common.api.InstanceConstraintViolationsListDTO;
import org.libreplan.ws.common.api.OrderDTO;
import org.libreplan.ws.common.api.OrderElementDTO;
import org.libreplan.ws.common.impl.ConfigurationOrderElementConverter;
import org.libreplan.ws.common.impl.ConstraintViolationConverter;
import org.libreplan.ws.common.impl.OrderElementConverter;
import org.libreplan.ws.common.impl.Util;
import org.libreplan.ws.subcontract.api.ISubcontractService;
import org.libreplan.ws.subcontract.api.SubcontractedTaskDataDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * REST-based implementation of {@link ISubcontractService}
 *
 * @author <NAME> <<EMAIL>>
 */
@Path("/subcontract/")
@Produces("application/xml")
@Service("subcontractServiceREST")
public class SubcontractServiceREST implements ISubcontractService {

    @Autowired
    private IOrderElementDAO orderElementDAO;

    @Autowired
    private IConfigurationDAO configurationDAO;

    @Autowired
    private IExternalCompanyDAO externalCompanyDAO;

    @Autowired
    private IEntitySequenceDAO entitySequenceDAO;

    @Autowired
    private IScenarioDAO scenarioDAO;

    @Autowired
    private ITaskSourceDAO taskSourceDAO;

    @Autowired
    private IAdHocTransactionService adHocTransactionService;

    static class ViolationError extends RuntimeException {
        private final List<InstanceConstraintViolationsDTO> violations;

        ViolationError(InstanceConstraintViolationsDTO... violations) {
            Validate.noNullElements(violations);
            this.violations = Arrays.asList(violations);
        }

        ViolationError(String code, String message) {
            this(createConstraintViolationFor(code, message));
        }

        public List<InstanceConstraintViolationsDTO> getViolations() {
            return violations;
        }

        public InstanceConstraintViolationsListDTO toViolationList() {
            return new InstanceConstraintViolationsListDTO(violations);
        }
    }

    @Override
    @POST
    @Consumes("application/xml")
    public InstanceConstraintViolationsListDTO subcontract(
            final SubcontractedTaskDataDTO subcontractedTaskDataDTO) {
        try {
            doSubcontract(subcontractedTaskDataDTO);
        } catch (ViolationError e) {
            return e.toViolationList();
        }
        return new InstanceConstraintViolationsListDTO();
    }

    private void doSubcontract(final SubcontractedTaskDataDTO subcontractedTask)
            throws ViolationError {

        if (StringUtils.isEmpty(subcontractedTask.externalCompanyNif)) {
            throw new ViolationError(subcontractedTask.subcontractedCode,
                    "external company ID not specified");
        }

        final ExternalCompany externalCompany = adHocTransactionService
                .runOnTransaction(new IOnTransaction<ExternalCompany>() {
                    @Override
                    public ExternalCompany execute() {
                        return findExternalCompanyFor(subcontractedTask);
                    }
                });
        if (!externalCompany.isClient()) {
            throw new ViolationError(subcontractedTask.externalCompanyNif,
                    "external company is not registered as client");
        }

        final OrderElementDTO orderElementDTO = subcontractedTask.orderElementDTO;
        if (orderElementDTO == null) {
            throw new ViolationError(subcontractedTask.subcontractedCode,
                    "task not specified");
        }
        try {
            adHocTransactionService
                    .runOnTransaction(new IOnTransaction<Void>() {

                        @Override
                        public Void execute() {
                            createOrder(subcontractedTask, externalCompany,
                                    orderElementDTO);
                            return null;
                        }
                    });
        } catch (ValidationException e) {
            InstanceConstraintViolationsDTO violation = ConstraintViolationConverter
                    .toDTO(new InstanceConstraintViolationsDTOId(Long.valueOf(1),
                            orderElementDTO.code, OrderDTO.ENTITY_TYPE), e);
            throw new ViolationError(violation);
        }
    }

    private void createOrder(
            final SubcontractedTaskDataDTO subcontractedTaskDataDTO,
            final ExternalCompany externalCompany,
            final OrderElementDTO orderElementDTO) throws ViolationError{
        Scenario current = Registry.getScenarioManager().getCurrent();
        OrderVersion version = OrderVersion.createInitialVersion(current);
        OrderElement orderElement = OrderElementConverter.toEntity(version,
                orderElementDTO,
                ConfigurationOrderElementConverter.noAdvanceMeasurements());

        Order order;
        if (orderElement instanceof Order) {
            order = (Order) orderElement;
            order.setVersionForScenario(current, version);
            order.useSchedulingDataFor(version);
        } else {
            order = wrapInOrder(current, version,
                    orderElement);
        }

        addOrderToDerivedScenarios(current, version, order);

        order.setCodeAutogenerated(true);
        String code = entitySequenceDAO.getNextEntityCode(EntityNameEnum.ORDER);
        if (code == null) {<commit_msg>Add the external code when a whole order is imported as subcontrated task.<commit_after>/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolóxico de Galicia
 * Copyright (C) 2010-2011 Igalia, S.L.
 *
 * This program 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, see <http://www.gnu.org/licenses/>.
 */

package org.libreplan.ws.subcontract.impl;

import static org.libreplan.web.I18nHelper._;

import java.util.Arrays;
import java.util.List;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.hibernate.NonUniqueResultException;
import org.libreplan.business.calendars.entities.BaseCalendar;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.daos.IEntitySequenceDAO;
import org.libreplan.business.common.entities.EntityNameEnum;
import org.libreplan.business.common.entities.EntitySequence;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.externalcompanies.daos.IExternalCompanyDAO;
import org.libreplan.business.externalcompanies.entities.ExternalCompany;
import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.orders.entities.OrderStatusEnum;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.orders.entities.TaskSource.IOptionalPersistence;
import org.libreplan.business.orders.entities.TaskSource.TaskSourceSynchronization;
import org.libreplan.business.planner.daos.ITaskSourceDAO;
import org.libreplan.business.scenarios.daos.IScenarioDAO;
import org.libreplan.business.scenarios.entities.OrderVersion;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.ws.common.api.InstanceConstraintViolationsDTO;
import org.libreplan.ws.common.api.InstanceConstraintViolationsDTOId;
import org.libreplan.ws.common.api.InstanceConstraintViolationsListDTO;
import org.libreplan.ws.common.api.OrderDTO;
import org.libreplan.ws.common.api.OrderElementDTO;
import org.libreplan.ws.common.impl.ConfigurationOrderElementConverter;
import org.libreplan.ws.common.impl.ConstraintViolationConverter;
import org.libreplan.ws.common.impl.OrderElementConverter;
import org.libreplan.ws.common.impl.Util;
import org.libreplan.ws.subcontract.api.ISubcontractService;
import org.libreplan.ws.subcontract.api.SubcontractedTaskDataDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * REST-based implementation of {@link ISubcontractService}
 *
 * @author <NAME> <<EMAIL>>
 */
@Path("/subcontract/")
@Produces("application/xml")
@Service("subcontractServiceREST")
public class SubcontractServiceREST implements ISubcontractService {

    @Autowired
    private IOrderElementDAO orderElementDAO;

    @Autowired
    private IConfigurationDAO configurationDAO;

    @Autowired
    private IExternalCompanyDAO externalCompanyDAO;

    @Autowired
    private IEntitySequenceDAO entitySequenceDAO;

    @Autowired
    private IScenarioDAO scenarioDAO;

    @Autowired
    private ITaskSourceDAO taskSourceDAO;

    @Autowired
    private IAdHocTransactionService adHocTransactionService;

    static class ViolationError extends RuntimeException {
        private final List<InstanceConstraintViolationsDTO> violations;

        ViolationError(InstanceConstraintViolationsDTO... violations) {
            Validate.noNullElements(violations);
            this.violations = Arrays.asList(violations);
        }

        ViolationError(String code, String message) {
            this(createConstraintViolationFor(code, message));
        }

        public List<InstanceConstraintViolationsDTO> getViolations() {
            return violations;
        }

        public InstanceConstraintViolationsListDTO toViolationList() {
            return new InstanceConstraintViolationsListDTO(violations);
        }
    }

    @Override
    @POST
    @Consumes("application/xml")
    public InstanceConstraintViolationsListDTO subcontract(
            final SubcontractedTaskDataDTO subcontractedTaskDataDTO) {
        try {
            doSubcontract(subcontractedTaskDataDTO);
        } catch (ViolationError e) {
            return e.toViolationList();
        }
        return new InstanceConstraintViolationsListDTO();
    }

    private void doSubcontract(final SubcontractedTaskDataDTO subcontractedTask)
            throws ViolationError {

        if (StringUtils.isEmpty(subcontractedTask.externalCompanyNif)) {
            throw new ViolationError(subcontractedTask.subcontractedCode,
                    "external company ID not specified");
        }

        final ExternalCompany externalCompany = adHocTransactionService
                .runOnTransaction(new IOnTransaction<ExternalCompany>() {
                    @Override
                    public ExternalCompany execute() {
                        return findExternalCompanyFor(subcontractedTask);
                    }
                });
        if (!externalCompany.isClient()) {
            throw new ViolationError(subcontractedTask.externalCompanyNif,
                    "external company is not registered as client");
        }

        final OrderElementDTO orderElementDTO = subcontractedTask.orderElementDTO;
        if (orderElementDTO == null) {
            throw new ViolationError(subcontractedTask.subcontractedCode,
                    "task not specified");
        }
        try {
            adHocTransactionService
                    .runOnTransaction(new IOnTransaction<Void>() {

                        @Override
                        public Void execute() {
                            createOrder(subcontractedTask, externalCompany,
                                    orderElementDTO);
                            return null;
                        }
                    });
        } catch (ValidationException e) {
            InstanceConstraintViolationsDTO violation = ConstraintViolationConverter
                    .toDTO(new InstanceConstraintViolationsDTOId(Long.valueOf(1),
                            orderElementDTO.code, OrderDTO.ENTITY_TYPE), e);
            throw new ViolationError(violation);
        }
    }

    private void createOrder(
            final SubcontractedTaskDataDTO subcontractedTaskDataDTO,
            final ExternalCompany externalCompany,
            final OrderElementDTO orderElementDTO) throws ViolationError{
        Scenario current = Registry.getScenarioManager().getCurrent();
        OrderVersion version = OrderVersion.createInitialVersion(current);
        OrderElement orderElement = OrderElementConverter.toEntity(version,
                orderElementDTO,
                ConfigurationOrderElementConverter.noAdvanceMeasurements());

        Order order;
        if (orderElement instanceof Order) {
            order = (Order) orderElement;
            order.setVersionForScenario(current, version);
            order.useSchedulingDataFor(version);
            order.setExternalCode(order.getCode());
        } else {
            order = wrapInOrder(current, version,
                    orderElement);
        }

        addOrderToDerivedScenarios(current, version, order);

        order.setCodeAutogenerated(true);
        String code = entitySequenceDAO.getNextEntityCode(EntityNameEnum.ORDER);
        if (code == null) {
{'fraction_non_alphanumeric': 0.07509623926562037, 'fraction_numerical': 0.0023689665383476457, 'mean_word_length': 3.2099227125405134, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6207517', 'n_tokens_mistral': 4470, 'n_tokens_neox': 4461, 'n_words': 915}