Package com.scooterframework.orm.activerecord

Source Code of com.scooterframework.orm.activerecord.ReferenceDataLoader$ReferenceDataTimerTask

/*
*   This software is distributed under the terms of the FSF
*   Gnu Lesser General Public License (see lgpl.txt).
*
*   This program is distributed WITHOUT ANY WARRANTY. See the
*   GNU General Public License for more details.
*/
package com.scooterframework.orm.activerecord;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;

import com.scooterframework.orm.sqldataexpress.config.DatabaseConfig;
import com.scooterframework.orm.sqldataexpress.object.RowData;
import com.scooterframework.orm.sqldataexpress.service.SqlServiceClient;

/**
* ReferenceDataLoader is responsible for loading reference data.
*
* @author (Fei) John Chen
*/
public class ReferenceDataLoader implements Observer {
    private static Map<String, ReferenceDataTimerTask> referenceDataTaskMap = new HashMap<String, ReferenceDataTimerTask>();
    private static long oneHundredDays = 8640000;
    private static boolean started = false;
    private Date oldDate = null;
    private Timer timer = null;

    public ReferenceDataLoader() {
        oldDate = new Date();
        oldDate.setTime(oldDate.getTime()-oneHundredDays);

        DatabaseConfig.getInstance().addObserver(this);
    }

    public void start() {
        if (started) return;

        timer = new Timer();

        List<String> refNames = DatabaseConfig.getInstance().getReferenceDataNames();
        if (refNames != null && refNames.size() > 0) {
            Iterator<String> it = refNames.iterator();
            while(it.hasNext()) {
                String name = it.next();
                Properties prop = DatabaseConfig.getInstance().getReferenceDataProperties(name);
                ReferenceDataTimerTask task = new ReferenceDataTimerTask(name, prop);
                referenceDataTaskMap.put(name, task);
                schedule(task, task.period);
            }
        }

        started = true;
    }

    /**
     * Terminates this loader, discarding any currently scheduled tasks.
     *
     * @see  java.util.Timer#cancel()
     */
    public void cancel() {
        timer.cancel();
    }

    /**
     * Terminates this loader, discarding any currently scheduled tasks.
     *
     * @see  java.util.Timer#cancel()
     */
    public void stop() {
        timer.cancel();
        started = false;
    }

    /**
     * Updates this loader, restarts the timer task if its period is changed.
     */
    public void update(Observable o, Object arg) {
        List<String> refNames = DatabaseConfig.getInstance().getReferenceDataNames();
        if (refNames != null && refNames.size() > 0) {
            Iterator<String> it = refNames.iterator();
            while(it.hasNext()) {
                String name = it.next();
                Properties prop = DatabaseConfig.getInstance().getReferenceDataProperties(name);
                if (referenceDataTaskMap.containsKey(name)) {
                    ReferenceDataTimerTask task = (ReferenceDataTimerTask)referenceDataTaskMap.get(name);
                    task.resetProperties(prop);
                    if (task.periodModified) {
                        task.cancel();
                        task = new ReferenceDataTimerTask(name, prop);
                        referenceDataTaskMap.put(name, task);
                        schedule(task, task.period);
                    }
                }
                else {
                    ReferenceDataTimerTask task = new ReferenceDataTimerTask(name, prop);
                    referenceDataTaskMap.put(name, task);
                    schedule(task, task.period);
                }
            }
        }

        //now remove all reference data tasks that have been removed from property file.
        for (Map.Entry<String, ReferenceDataTimerTask> entry : referenceDataTaskMap.entrySet()) {
          String name = entry.getKey();
            if (!refNames.contains(name)) {
                ReferenceDataTimerTask task = entry.getValue();
                task.cancel();
                referenceDataTaskMap.remove(name);
            }
        }
    }

    public static boolean isStarted() {
        return started;
    }

    public static Map<String, ReferenceDataTimerTask>  getReferenceDataTasks() {
        return referenceDataTaskMap;
    }

    private void schedule(TimerTask task, long period) {
        if (period > 0) {
            timer.schedule(task, oldDate, period);
        }
        else {
            timer.schedule(task, oldDate);
        }
    }

    private static class ReferenceDataTimerTask extends TimerTask {
        String theName = "";
        String clz = null;
        String sql = null;
        String key = "";
        String value = "";
        long period = 0;//in milliseconds
        Date loadedTime = null;
        boolean hasRun = false;
        boolean periodModified = false;
        boolean runOnlyOnce = false;
        boolean donotRun = false;

        public ReferenceDataTimerTask(String name, Properties prop) {
            super();
            theName = name;
            init(prop);
        }

        private void init(Properties prop) {
            clz = prop.getProperty("class");
            sql = prop.getProperty("sql");
            if (clz == null && sql == null)
                throw new IllegalArgumentException("Either clz or sql must be specified for reference data " + theName + ".");

            key = prop.getProperty("key");
            value = prop.getProperty("value");

            long thePeriod = 0;
            try {
                thePeriod = Long.parseLong(prop.getProperty("period", "0"));
            }
            catch(NumberFormatException nfex) {
                thePeriod = 0;
            }

            periodModified = false;
            //if ((hasRun && (thePeriod != 0) || !hasRun && (thePeriod == 0)) && (period != thePeriod)) {
            if (period != thePeriod) {
                periodModified = true;
            }

            period = thePeriod;

            if (period == 0) {
                runOnlyOnce = true;
            }
            else if (period < 0) {
                donotRun = true;
            }
        }

        public void resetProperties(Properties prop) {
            init(prop);
        }

        public void run() {
            if (donotRun || (runOnlyOnce && hasRun)) return;

            if (clz != null) {
                List<ActiveRecord> records = null;
                if (sql != null) {
                    records = ActiveRecordUtil.getGateway(clz).findAllBySQL(sql);
                }
                else {
                    records = ActiveRecordUtil.getGateway(clz).findAll();
                }
                ReferenceDataStore.setReferenceData(theName, convertRecordsToReferenceDataList(records));
            }
            else {
                List<RowData> rows = SqlServiceClient.retrieveRowsBySQL(sql);
                ReferenceDataStore.setReferenceData(theName, convertRowsToReferenceDataList(rows));
            }

            loadedTime = new Date();
            hasRun = true;
        }

        public String toString() {
            StringBuilder sb = new StringBuilder();
            sb.append("name=" + theName).append(", ");
            sb.append("clz=" + clz).append(", ");
            sb.append("sql=" + sql).append(", ");
            sb.append("key=" + key).append(", ");
            sb.append("value=" + value).append(", ");
            sb.append("period=" + period).append(", ");
            sb.append("loadedTime=" + loadedTime);
            return sb.toString();
        }

        private List<ReferenceData> convertRecordsToReferenceDataList(List<ActiveRecord> records) {
            if (records == null) return null;

            List<ReferenceData> list = new ArrayList<ReferenceData>(records.size());
            Iterator<ActiveRecord> it = records.iterator();
            while(it.hasNext()) {
                ActiveRecord record = it.next();
                ReferenceDataRecord rdr = new ReferenceDataRecord(theName, key, value, record);
                list.add(rdr);
            }
            return list;
        }

        private List<ReferenceData> convertRowsToReferenceDataList(List<RowData> records) {
            if (records == null) return null;

            List<ReferenceData> list = new ArrayList<ReferenceData>(records.size());
            Iterator<RowData> it = records.iterator();
            while(it.hasNext()) {
                RowData row = it.next();
                ReferenceData rdr = new ReferenceDataRecord(theName, key, value, row);
                list.add(rdr);
            }
            return list;
        }
    }
}
TOP

Related Classes of com.scooterframework.orm.activerecord.ReferenceDataLoader$ReferenceDataTimerTask

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.