package alien4cloud.csar.services;

import alien4cloud.dao.IGenericSearchDAO;
import alien4cloud.dao.model.GetMultipleDataResult;
import alien4cloud.exception.AlreadyExistException;
import alien4cloud.exception.InvalidArgumentException;
import alien4cloud.exception.NotFoundException;
import alien4cloud.model.git.CsarGitCheckoutLocation;
import alien4cloud.model.git.CsarGitRepository;
import alien4cloud.utils.UrlUtil;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;

/**
 * Manages operations on a CsarGitRepository
 */
@Slf4j
@Service
public class CsarGitRepositoryService {
    private static final String URL_FIELD = "repositoryUrl";
    @Resource(name = "alien-es-dao")
    private IGenericSearchDAO alienDAO;

    private static final String forbiddenSubPathCharacter = "*";

    /**
     * Create a CsarGitRepository in the system to store its informations
     *
     * @param repositoryUrl The unique Git url of the CsarGitRepository
     * @param username The username of the user
     * @param password The password of the user
     * @param importLocations Locations where Csar's files are store
     * @param isStoredLocally The state of the the CsarGitRepository
     * @return The auto-generated id of the CsarGitRepository object
     */
    public String create(String repositoryUrl, String username, String password, List<CsarGitCheckoutLocation> importLocations, boolean isStoredLocally) {
        validatesRepositoryUrl(repositoryUrl);
        failIfExists(repositoryUrl);
        validatesImportLocations(importLocations);
        // create it
        CsarGitRepository csarGit = new CsarGitRepository();
        csarGit.setId(UUID.randomUUID().toString());
        csarGit.setRepositoryUrl(repositoryUrl);
        csarGit.setUsername(username);
        csarGit.setPassword(password);
        csarGit.setImportLocations(importLocations);
        csarGit.setStoredLocally(isStoredLocally);
        alienDAO.save(csarGit);
        return csarGit.getId();
    }

    private void validatesImportLocations(List<CsarGitCheckoutLocation> importLocations) {
        if (importLocations.isEmpty()) {
            throw new InvalidArgumentException("Import locations cannot be empty.");
        }
        importLocations.stream().forEachOrdered(location -> {
            if (forbiddenSubPatchCharacter.equals(location.getSubPath())) {
                location.setSubPath(null);
                log.debug("The path file cannot be the special character : <" + forbiddenSubPatchCharacter + ">. All files will be imported.");
            }
        });
    }

    private void validatesRepositoryUrl(String repositoryUrl) {
        // check if the repository url has a valid format
        if (!UrlUtil.isValid(repositoryUrl)) {
            throw new InvalidArgumentException("Repository url <" + repositoryUrl + "> is not a valid url.");
        }
    }

    private void failIfExists(String repositoryUrl) {
        CsarGitRepository existingCsarGitRepository = alienDAO.customFind(CsarGitRepository.class, QueryBuilders.termQuery(URL_FIELD, repositoryUrl));
        if (existingCsarGitRepository != null) {
            throw new AlreadyExistException("A repository with url <" + repositoryUrl + "> already exists in alien 4 cloud.");
        }
    }

    /**
     * Get the csar git repository matching the given id or throw a NotFoundException
     *
     * @param id Id of the csar git repository that we want to get.
     * @return An instance of the csar git repository.
     */
    public CsarGitRepository getOrFail(String id) {
        CsarGitRepository csarGitRepository = alienDAO.findById(CsarGitRepository.class, id);
        if (csarGitRepository == null) {
            throw new NotFoundException("CSAR Git repository [" + id + "] doesn't exists.");
        }
        return csarGitRepository;
    }

    /**
     * Get multiple csar git repositories.
     *
     * @param query The query to apply to filter csar git repositories.
     * @param from The start index of the query.
     * @param size The maximum number of elements to return.
     * @return A {@link GetMultipleDataResult} that contains CsarGitRepository objects.
     */
    public GetMultipleDataResult<CsarGitRepository> search(String query, int from, int size) {
        return alienDAO.search(CsarGitRepository.class, query, null, from, size);
    }

    /**
     * Update informations for a given CsarGitRepository.
     *
     * @param id The id of the CsarGitRepository to update.
     * @param repositoryUrl The new url of the CsarGitRepository
     * @param username The username associated to the CsarGitRepository
     * @param password The password associated to the CsarGitRepository
     * @param importLocations
     * @param isStoredLocally
     */
    public void update(String id, String repositoryUrl, String username, String password, List<CsarGitCheckoutLocation> importLocations,
            boolean isStoredLocally) {
        validatesRepositoryUrl(repositoryUrl);
        CsarGitRepository repositoryToUpdate = getOrFail(id);
        if (!repositoryToUpdate.getRepositoryUrl().equals(repositoryUrl)) {
            failIfExists(repositoryUrl);
            repositoryToUpdate.setRepositoryUrl(repositoryUrl);
        }
        if (username != null) {
            repositoryToUpdate.setUsername(username);
        }
        if (password != null) {
            repositoryToUpdate.setPassword(password);
        }
        repositoryToUpdate.setStoredLocally(isStoredLocally);

        // just merge the existing location hash into new list so that we don't loose this information
        for (CsarGitCheckoutLocation location : importLocations) {
            CsarGitCheckoutLocation existingLocation = findLocationIn(location, repositoryToUpdate.getImportLocations());
            if (existingLocation != null) {
                location.setLastImportedHash(existingLocation.getLastImportedHash());
            }
            if (forbiddenSubPatchCharacter.equals(location.getSubPath())) {
                location.setSubPath(null);
                log.debug("The path file cannot be the special character : <" + forbiddenSubPatchCharacter + ">. All files will be imported.");
            }
        }
        repositoryToUpdate.setImportLocations(importLocations);

        alienDAO.save(repositoryToUpdate);
    }

    private CsarGitCheckoutLocation findLocationIn(CsarGitCheckoutLocation location, List<CsarGitCheckoutLocation> importLocations) {
        for (CsarGitCheckoutLocation givenLocation : importLocations) {
            if (givenLocation.getBranchId().equals(location.getBranchId())
                    && ((Strings.isNullOrEmpty(givenLocation.getSubPath()) && Strings.isNullOrEmpty(location.getSubPath()))
                            || (!Strings.isNullOrEmpty(givenLocation.getSubPath()) && givenLocation.getSubPath().equals(location.getSubPath())))) {
                return givenLocation;
            }
        }
        return null;
    }
}

@@ -2493,33 +2493,32 @@
 (forbiddenSubPat
-c
 hCharacter.equal
@@ -2675,33 +2675,32 @@
  forbiddenSubPat
-c
 hCharacter + %22%3E.
@@ -6141,33 +6141,32 @@
 (forbiddenSubPat
-c
 hCharacter.equal
@@ -6331,17 +6331,16 @@
 enSubPat
-c
 hCharact

Rename the all subpath symbol