/*-
 * ============LICENSE_START=======================================================
 * OSAM Core
 * ================================================================================
 * Copyright (C) 2018 Netsia
 * ================================================================================
 * Licensed 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
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * 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.
 * ============LICENSE_END=========================================================
 */



package org.onap.osam.core;

import org.onap.osam.common.exception.NotFoundException;
import org.onap.osam.model.dao.BaseEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.repository.CrudRepository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * Created by cemturker on 18.09.2018.
 */

public abstract class AbstractBaseServiceImpl {

    protected Logger log = LoggerFactory.getLogger(this.getClass());

    protected <T extends BaseEntity> T add(T t, CrudRepository<T, Long> repository) {
        t = repository.save(t);
        log.info("{} is added",t);
        return t;
    }

    protected <T extends BaseEntity> void remove(Long id, CrudRepository<T, Long> repository, Class classz) {
        repository.deleteById(id);
        log.info("{} is deleted for {}", id, classz.getName());
    }

    protected <T extends BaseEntity> T get(Long id, CrudRepository<T, Long> repository) {
        Optional<T> optional = repository.findById(id);
        if (!optional.isPresent()) {
            throw new NotFoundException("id:"+id+" is not found");
        }
        return optional.get();
    }

    protected <T extends BaseEntity> List<T> getAll(CrudRepository<T, Long> repository) {
        List<T> ts = new ArrayList<>();
        repository.findAll().iterator().forEachRemaining(ts::add);
        return Collections.unmodifiableList(ts);
    }

    protected <T extends BaseEntity> Long count(CrudRepository<T, Long> repository) {
        return repository.count();
    }
}
