org.apache.ambari.view.registry.web.service.ApplicationService.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.ambari.view.registry.web.service.ApplicationService.java

Source

/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.apache.ambari.view.registry.web.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.zafarkhaja.semver.Version;
import lombok.extern.slf4j.Slf4j;
import org.apache.ambari.view.registry.internal.exception.ConfigFileParseException;
import org.apache.ambari.view.registry.internal.exception.ConfigSerializationException;
import org.apache.ambari.view.registry.internal.exception.ConfigValidationException;
import org.apache.ambari.view.registry.internal.exception.ConfigVersionMismatchException;
import org.apache.ambari.view.registry.web.config.ApplicationConfig;
import org.apache.ambari.view.registry.web.model.entity.Application;
import org.apache.ambari.view.registry.web.model.entity.ApplicationVersion;
import org.apache.ambari.view.registry.web.model.repository.ApplicationRepository;
import org.apache.ambari.view.registry.web.model.repository.ApplicationVersionRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/**
 * Service class to work on the application definations
 */
@Service
@Slf4j
public class ApplicationService {

    private final ApplicationRepository applicationRepository;
    private final ApplicationVersionRepository applicationVersionRepository;

    @Autowired
    public ApplicationService(ApplicationRepository applicationRepository,
            ApplicationVersionRepository applicationVersionRepository) {
        this.applicationRepository = applicationRepository;
        this.applicationVersionRepository = applicationVersionRepository;
    }

    public ApplicationConfig parseApplicationConfig(InputStream stream, String orgFileName) {
        ObjectMapper mapper = new ObjectMapper();
        ApplicationConfig config = null;
        try {
            config = mapper.readValue(stream, ApplicationConfig.class);
        } catch (IOException e) {
            log.error("Failed to parse the stream for application config. {} not a valid json file. Exception: {}",
                    orgFileName, e);
            throw new ConfigFileParseException(orgFileName, e);
        }
        validate(config, orgFileName);
        return config;
    }

    private void validate(ApplicationConfig config, String orgFileName) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();
        Set<ConstraintViolation<ApplicationConfig>> contraints = validator.validate(config);
        if (contraints.size() != 0) {
            log.info("Constraints: {}", contraints);
            log.error("Failed to validate application config defined in {}. Exceptions: {}", orgFileName,
                    contraints);
            throw new ConfigValidationException(orgFileName, contraints);
        }
    }

    @Transactional
    public ApplicationVersion saveApplicationConfig(ApplicationConfig config) {
        Optional<Application> applicationOptional = applicationRepository.findByName(config.getName());

        Application application = applicationOptional.orElseGet(() -> {
            Application app = new Application();
            app = new Application();
            app.setName(config.getName());
            return app;
        });

        application.setDescription(config.getDescription());
        application.setLabel(config.getLabel());
        application.setUpdatedAt(new Date());

        validateVersionIsGreater(config, application);

        ApplicationVersion version = new ApplicationVersion();
        version.setApplication(application);
        try {
            version.setApplicationConfig(getJsonString(config));
        } catch (JsonProcessingException e) {
            log.error("Failed to serialize configuration to JSON string for {}", config);
            throw new ConfigSerializationException(e);
        }

        version.setVersion(config.getVersion());
        version.setCreatedAt(new Date());

        application.getVersions().add(version);
        applicationRepository.save(application);

        return applicationVersionRepository.save(version);
    }

    private void validateVersionIsGreater(ApplicationConfig config, Application application) {
        Optional<ApplicationVersion> maxVersionOptional = getMaxVersion(application);

        if (maxVersionOptional.isPresent()) {
            ApplicationVersion maxVersion = maxVersionOptional.get();
            if (Version.valueOf(config.getVersion()).lessThanOrEqualTo(Version.valueOf(maxVersion.getVersion()))) {
                String errMessage = String.format(
                        "'%s' should be greater than exiting max version '%s' for application '%s'",
                        config.getVersion(), maxVersion.getVersion(), config.getName());
                log.error(errMessage);
                throw new ConfigVersionMismatchException(errMessage);
            }
        }
    }

    private Optional<ApplicationVersion> getMaxVersion(Application application) {
        return application.getVersions().stream()
                .max((v1, v2) -> Version.valueOf(v1.getVersion()).compareTo(Version.valueOf(v2.getVersion())));
    }

    private String getJsonString(ApplicationConfig config) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.writeValueAsString(config);
    }

    public List<Application> findApplications(Optional<String> appNameLike, Optional<Long> after) {
        List<Application> applications = new ArrayList<>();
        if (appNameLike.isPresent() && after.isPresent()) {
            applications = applicationRepository
                    .findByNameLikeAndUpdatedAtGreaterThan("%" + appNameLike.get() + "%", new Date(after.get()));
        } else if (appNameLike.isPresent()) {
            applications = applicationRepository.findByNameLike("%" + appNameLike.get() + "%");
        } else if (after.isPresent()) {
            applications = applicationRepository.findByUpdatedAtGreaterThan(new Date(after.get()));
        }
        return applications;
    }

    public Optional<Application> findApplicationByName(String appName) {
        return applicationRepository.findByName(appName);
    }

    public Optional<ApplicationVersion> findApplicationVersion(String appName, String version) {
        Optional<Application> application = applicationRepository.findByName(appName);
        if (application.isPresent()) {
            if ("latest".equalsIgnoreCase(version)) {
                return getMaxVersion(application.get());
            } else {
                return application.get().getVersions().stream()
                        .filter(v -> version.equalsIgnoreCase(v.getVersion())).findFirst();
            }
        }
        return Optional.empty();
    }

    public Optional<ApplicationVersion> publishVersion(String appName, String versionNumber, boolean publish) {
        ApplicationVersion modifiedVersion = null;
        Optional<Application> application = applicationRepository.findByName(appName);
        if (application.isPresent()) {
            Optional<ApplicationVersion> ver = application.get().getVersions().stream()
                    .filter(v -> versionNumber.equalsIgnoreCase(v.getVersion())).findFirst();

            if (ver.isPresent()) {
                ApplicationVersion version = ver.get();
                version.setPublished(publish);
                modifiedVersion = applicationVersionRepository.save(version);
            }
        }
        return Optional.ofNullable(modifiedVersion);
    }
}