net.solarnetwork.node.job.DatumDataSourceLoggerJob.java Source code

Java tutorial

Introduction

Here is the source code for net.solarnetwork.node.job.DatumDataSourceLoggerJob.java

Source

/* ===================================================================
 * DatumDataSourceLoggerJob.java
 * 
 * Created Dec 1, 2009 4:35:24 PM
 * 
 * Copyright 2007-2009 SolarNetwork.net Dev Team
 * 
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License as 
 * published by the Free Software Foundation; either version 2 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 
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
 * 02111-1307 USA
 * ===================================================================
 */

package net.solarnetwork.node.job;

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import net.solarnetwork.node.DatumDataSource;
import net.solarnetwork.node.MultiDatumDataSource;
import net.solarnetwork.node.dao.DatumDao;
import net.solarnetwork.node.domain.Datum;
import org.quartz.JobExecutionContext;
import org.quartz.StatefulJob;
import org.springframework.dao.DuplicateKeyException;

/**
 * Job to collect data from a {@link DatumDataSource} and persist that via a
 * {@link DatumDao}.
 * 
 * <p>
 * This job simply calls {@link DatumDataSource#readCurrentDatum()} and if that
 * returns a non-null object, passes that to {@link DatumDao#storeDatum(Datum)}.
 * In essence, this job is for reading the current data available on some device
 * and then persisting it to a (probably local) database.
 * </p>
 * 
 * <p>
 * If the configured {@code datumDataSource} implements
 * {@link MultiDatumDataSource} and the Class returned by
 * {@link MultiDatumDataSource#getMultiDatumType()} is assignable to the Class
 * returned by {@link DatumDataSource#getDatumType()} then
 * {@link MultiDatumDataSource#readMultipleDatum()} will be called instead of
 * {@link DatumDataSource#readCurrentDatum()}. Each {@code Datum} returned in
 * the resulting Collection will be persisted to the configured {@link DatumDao}
 * .
 * </p>
 * 
 * <p>
 * The configurable properties of this class are:
 * </p>
 * 
 * <dl class="class-properties">
 * <dt>datumDataSource</dt>
 * <dd>The {@link DatumDataSource} to collect the data from. The
 * {@link DatumDataSource#readCurrentDatum()} method will be called to get the
 * currently available data.</dd>
 * 
 * <dt>datumDao</dt>
 * <dd>The {@link DatumDao} to persist the collected data to. The
 * {@link DatumDao#storeDatum(Datum)} method will be called with the
 * {@link Datum} returned by {@link DatumDataSource#readCurrentDatum()}, if it
 * is non-null.</dd>
 * </dl>
 * 
 * @param <T>
 *        the Datum type for this job
 * @author matt
 * @version 1.1
 */
public class DatumDataSourceLoggerJob<T extends Datum> extends AbstractJob implements StatefulJob {

    private List<DatumDataSource<T>> datumDataSources = null;
    private DatumDao<T> datumDao = null;

    @Override
    protected void executeInternal(JobExecutionContext jobContext) throws Exception {
        for (DatumDataSource<T> datumDataSource : datumDataSources) {
            try {
                if (log.isDebugEnabled()) {
                    log.debug("Collecting [{}] from [{}]", datumDataSource.getDatumType().getSimpleName(),
                            datumDataSource);
                }

                Collection<T> datumList = null;
                if (datumDataSource instanceof MultiDatumDataSource<?>) {
                    datumList = readMultiDatum(datumDataSource);
                }
                if (datumList == null) {
                    T datum = datumDataSource.readCurrentDatum();
                    if (datum != null) {
                        datumList = new LinkedList<T>();
                        datumList.add(datum);
                    }
                }
                if (datumList == null || datumList.isEmpty()) {
                    if (log.isInfoEnabled()) {
                        log.info("No data returned from [{}]", datumDataSource);
                    }
                    continue;
                }

                if (log.isInfoEnabled()) {
                    log.info("Got Datum to persist: {}",
                            (datumList.size() == 1 ? datumList.iterator().next().toString()
                                    : datumList.toString()));
                }
                for (T datum : datumList) {
                    try {
                        datumDao.storeDatum(datum);
                        log.debug("Persisted Datum {}", datum);
                    } catch (DuplicateKeyException e) {
                        // we ignore duplicate key exceptions, as we sometimes collect the same 
                        // datum multiple times for redundancy
                        log.info("Duplicate datum {}; not persisting", datum);
                    }
                }
            } catch (Throwable e) {
                logThrowable(e);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private Collection<T> readMultiDatum(DatumDataSource<T> datumDataSource) {
        MultiDatumDataSource<T> multi = (MultiDatumDataSource<T>) datumDataSource;
        if (!datumDataSource.getDatumType().isAssignableFrom(multi.getMultiDatumType())) {
            return null;
        }
        return multi.readMultipleDatum();
    }

    public DatumDataSource<T> getDatumDataSource() {
        return datumDataSources == null || datumDataSources.size() < 1 ? null : datumDataSources.get(0);
    }

    public void setDatumDataSource(DatumDataSource<T> datumDataSource) {
        if (this.datumDataSources == null) {
            this.datumDataSources = new ArrayList<DatumDataSource<T>>(2);
        }
        this.datumDataSources.clear();
        this.datumDataSources.add(datumDataSource);
    }

    public List<DatumDataSource<T>> getDatumDataSources() {
        return datumDataSources;
    }

    public void setDatumDataSources(List<DatumDataSource<T>> datumDataSources) {
        this.datumDataSources = datumDataSources;
    }

    public DatumDao<T> getDatumDao() {
        return datumDao;
    }

    public void setDatumDao(DatumDao<T> datumDao) {
        this.datumDao = datumDao;
    }

}