org.openlmis.fulfillment.AuditLogInitializer.java Source code

Java tutorial

Introduction

Here is the source code for org.openlmis.fulfillment.AuditLogInitializer.java

Source

/*
 * This program is part of the OpenLMIS logistics management information system platform software.
 * Copyright  2017 VillageReach
 *
 * 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. For additional information contact info@OpenLMIS.org.
 */

package org.openlmis.fulfillment;

import static org.openlmis.fulfillment.util.Pagination.DEFAULT_PAGE_NUMBER;

import org.javers.core.Javers;
import org.javers.core.metamodel.object.CdoSnapshot;
import org.javers.repository.jql.QueryBuilder;
import org.javers.spring.annotation.JaversSpringDataAuditable;
import org.openlmis.fulfillment.domain.BaseEntity;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
import org.slf4j.profiler.Profiler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Profile;
import org.springframework.core.annotation.Order;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

/**
 * AuditLogInitializer runs after its associated Spring application has loaded.
 * It examines each domain object in the database and registers them with JaVers
 * if they haven't already been so. This is, in part, a fix for
 * <a href="https://github.com/javers/javers/issues/214">this issue</a>.
 */
@Component
@Profile("refresh-db")
@Order(20)
@Transactional
public class AuditLogInitializer implements CommandLineRunner {
    private static final XLogger LOGGER = XLoggerFactory.getXLogger(AuditLogInitializer.class);

    @Autowired
    private ApplicationContext applicationContext;

    @Resource(name = "javersProvider")
    private Javers javers;

    /**
     * This method is part of CommandLineRunner and is called automatically by Spring.
     * @param args Main method arguments.
     */
    @Override
    public void run(String... args) {
        LOGGER.entry();
        Profiler profiler = new Profiler("RUN_AUDIT_LOG_INIT");
        profiler.setLogger(LOGGER);

        profiler.start("GET_AUDITABLE_REPOSITORIES");
        //Get all JaVers repositories.
        Map<String, Object> repositoryMap = applicationContext
                .getBeansWithAnnotation(JaversSpringDataAuditable.class);

        //For each one...
        for (Map.Entry<String, Object> entry : repositoryMap.entrySet()) {
            String beanName = entry.getKey();
            Object bean = entry.getValue();
            profiler.start("CREATE_SNAPSHOTS_OF_" + beanName);
            createSnapshots(bean);
        }

        profiler.stop().log();
        LOGGER.exit();
    }

    private void createSnapshots(Object bean) {
        if (bean instanceof PagingAndSortingRepository) {
            createSnapshots((PagingAndSortingRepository<?, ?>) bean);
        } else if (bean instanceof CrudRepository) {
            createSnapshots((CrudRepository<?, ?>) bean);
        }
    }

    private void createSnapshots(PagingAndSortingRepository<?, ?> repository) {
        Pageable pageable = new PageRequest(DEFAULT_PAGE_NUMBER, 2000);

        while (true) {
            Page<?> page = repository.findAll(pageable);

            if (!page.hasContent()) {
                break;
            }

            page.forEach(this::createSnapshot);

            pageable = pageable.next();
        }
    }

    private void createSnapshots(CrudRepository<?, ?> repository) {
        //... retrieve all of its domain objects and...
        repository.findAll().forEach(this::createSnapshot);
    }

    private void createSnapshot(Object object) {
        //...check whether there exists a snapshot for it in the audit log.
        // Note that we don't care about checking for logged changes, per se,
        // and thus use findSnapshots() rather than findChanges()
        BaseEntity baseEntity = (BaseEntity) object;

        QueryBuilder jqlQuery = QueryBuilder.byInstanceId(baseEntity.getId(), object.getClass());
        List<CdoSnapshot> snapshots = javers.findSnapshots(jqlQuery.build());

        //If there are no snapshots of the domain object, then take one
        if (snapshots.size() == 0) {
            javers.commit("System: AuditLogInitializer", baseEntity);
        }
    }

}