/** * Axelor Business Solutions * * Copyright (C) 2016 Axelor (<http://axelor.com>). * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License, version 3, * as published by the Free Software Foundation. * * 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 com.axelor.apps.base.service.administration; import java.lang.reflect.Field; import org.joda.time.DateTime; import org.joda.time.Interval; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.axelor.apps.base.db.Batch; import com.axelor.apps.base.db.repo.BatchRepository; import com.axelor.apps.base.exceptions.IExceptionMessage; import com.axelor.auth.db.AuditableModel; import com.axelor.db.JPA; import com.axelor.db.Model; import com.axelor.exception.AxelorException; import com.axelor.i18n.I18n; import com.google.common.base.Preconditions; import com.google.inject.Inject; import com.google.inject.persist.Transactional; public abstract class AbstractBatch { @Inject protected GeneralService generalService; static final Logger LOG = LoggerFactory.getLogger(AbstractBatch.class); protected Batch batch; protected Model model; private int done, anomaly; @Inject protected BatchRepository batchRepo; protected AbstractBatch( ){ this.batch = new Batch(); this.batch.setStartDate(new DateTime()); this.done = 0; this.anomaly = 0; this.batch.setDone(this.done); this.batch.setAnomaly(this.anomaly); } public Batch getBatch(){ return batch; } public Batch run( AuditableModel model ){ Preconditions.checkNotNull(model); if ( isRunnable( model ) ) { try { start(); process(); stop(); return batch; } catch (Exception e) { unarchived(); throw new RuntimeException(e); } } else { throw new RuntimeException(I18n.get(IExceptionMessage.ABSTRACT_BATCH_1)); } } abstract protected void process(); protected boolean isRunnable ( Model model ) { this.model = model; if (model.getArchived() != null) { return !model.getArchived() ; } else { return true; } } protected void start() throws IllegalArgumentException, IllegalAccessException, AxelorException { LOG.info("Début batch {} ::: {}", new Object[]{ model, batch.getStartDate() }); model.setArchived(true); associateModel(); checkPoint(); } /** * As {@code batch} entity can be detached from the session, call {@code Batch.find()} get the entity in the persistant context. * Warning : {@code batch} entity have to be saved before. */ protected void stop(){ batch = batchRepo.find( batch.getId() ); batch.setEndDate( new DateTime() ); batch.setDuration( getDuring() ); checkPoint(); unarchived(); LOG.info("Fin batch {} ::: {}", new Object[]{ model, batch.getEndDate() }); } protected void incrementDone(){ batch = batchRepo.find( batch.getId() ); done += 1; batch.setDone( done ); checkPoint(); LOG.debug("Done ::: {}", done); } protected void incrementAnomaly(){ batch = batchRepo.find( batch.getId() ); anomaly += 1; batch.setAnomaly(anomaly); checkPoint(); LOG.debug("Anomaly ::: {}", anomaly); } protected void addComment(String comment){ batch = batchRepo.find( batch.getId() ); batch.setComments(comment); checkPoint(); } @Transactional protected Batch checkPoint(){ return batchRepo.save(batch); } @Transactional protected void unarchived() { model = JPA.find(generalService.getPersistentClass(model), model.getId()); model.setArchived( false ); } private int getDuring(){ return new Interval(batch.getStartDate(), batch.getEndDate()).toDuration().toStandardSeconds().toStandardMinutes().getMinutes(); } private void associateModel() throws IllegalArgumentException, IllegalAccessException{ LOG.debug("ASSOCIATE batch:{} TO model:{}", new Object[] { batch, model }); for (Field field : batch.getClass().getDeclaredFields()){ LOG.debug("TRY TO ASSOCIATE field:{} TO model:{}", new Object[] { field.getType().getName(), model.getClass().getName() }); if ( isAssociable(field) ){ LOG.debug("FIELD ASSOCIATE TO MODEL"); field.setAccessible(true); field.set(batch, model); field.setAccessible(false); break; } } } private boolean isAssociable(Field field){ return field.getType().equals( generalService.getPersistentClass(model) ); } }