/** * * Funf: Open Sensing Framework * Copyright (C) 2010-2011 Nadav Aharony, Wei Pan, Alex Pentland. * Acknowledgments: Alan Gardner * Contact: nadav@media.mit.edu * * Author(s): Pararth Shah (pararthshah717@gmail.com) * * This file is part of Funf. * * Funf is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * Funf 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Funf. If not, see <http://www.gnu.org/licenses/>. * */ package edu.mit.media.funf.pipeline; import java.util.List; import java.util.Map; import android.content.Context; import android.database.sqlite.SQLiteOpenHelper; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import com.google.gson.JsonElement; import edu.mit.media.funf.FunfManager; import edu.mit.media.funf.action.ActionAdapter; import edu.mit.media.funf.action.RunArchiveAction; import edu.mit.media.funf.action.RunUpdateAction; import edu.mit.media.funf.action.RunUploadAction; import edu.mit.media.funf.action.WriteDataAction; import edu.mit.media.funf.config.ConfigUpdater; import edu.mit.media.funf.config.Configurable; import edu.mit.media.funf.datasource.StartableDataSource; import edu.mit.media.funf.json.IJsonObject; import edu.mit.media.funf.json.JsonUtils; import edu.mit.media.funf.probe.Probe; import edu.mit.media.funf.probe.Probe.DataListener; import edu.mit.media.funf.storage.DefaultArchive; import edu.mit.media.funf.storage.FileArchive; import edu.mit.media.funf.storage.NameValueDatabaseHelper; import edu.mit.media.funf.storage.RemoteFileArchive; import edu.mit.media.funf.storage.UploadService; import edu.mit.media.funf.util.StringUtil; public class BasicPipeline implements Pipeline, DataListener { public static final String ACTION_ARCHIVE = "archive", ACTION_UPLOAD = "upload", ACTION_UPDATE = "update"; @Configurable protected String name = "actiongraph"; @Configurable protected int version = 1; @Configurable protected FileArchive archive = null; @Configurable protected RemoteFileArchive upload = null; @Configurable protected ConfigUpdater update = null; @Configurable protected List<StartableDataSource> data = null; @Configurable protected Map<String, StartableDataSource> schedules = null; private UploadService uploader; private boolean enabled; private FunfManager manager; private SQLiteOpenHelper databaseHelper = null; private Looper looper; private Handler handler; private WriteDataAction writeAction; private RunArchiveAction archiveAction; private RunUploadAction uploadAction; private RunUpdateAction updateAction; // private class DataRequestInfo { // private DataListener listener; // private JsonElement checkpoint; // } // // private StateListener probeStateListener = new StateListener() { // @Override // public void onStateChanged(Probe probe, State previousState) { // if (probe instanceof ContinuableProbe && previousState == State.RUNNING) { // JsonElement checkpoint = ((ContinuableProbe)probe).getCheckpoint(); // IJsonObject config = (IJsonObject)JsonUtils.immutable(getFunfManager().getGson().toJsonTree(probe)); // for (DataRequestInfo requestInfo : activeDataRequests.get(config)) { // requestInfo.checkpoint = checkpoint; // } // } // } // }; public IJsonObject getImmutableProbeConfig(String probeConfig) { Probe probe = getFunfManager().getGson().fromJson(probeConfig, Probe.class); IJsonObject probeJson = (IJsonObject)JsonUtils.immutable( getFunfManager().getGson().toJsonTree(probe)); return probeJson; } protected void setupDataSources() { if (enabled == false) { for (StartableDataSource dataSource: data) { dataSource.setListener((DataListener)writeAction); } if (schedules != null) { if (schedules.containsKey("archive")) { DataListener archiveListener = (DataListener)new ActionAdapter(archiveAction); schedules.get("archive").setListener(archiveListener); schedules.get("archive").start(); } if (schedules.containsKey("upload")) { DataListener uploadListener = (DataListener)new ActionAdapter(uploadAction); schedules.get("upload").setListener(uploadListener); schedules.get("upload").start(); } if (schedules.containsKey("update")) { DataListener updateListener = (DataListener)new ActionAdapter(updateAction); schedules.get("update").setListener(updateListener); schedules.get("update").start(); } } for (StartableDataSource dataSource: data) { dataSource.start(); } enabled = true; } } private void destroyDataSources() { if (enabled == true) { for (StartableDataSource dataSource: data) { dataSource.stop(); } enabled = false; } } @Override public void onCreate(FunfManager manager) { if (archive == null) { archive = new DefaultArchive(manager, name); } if (uploader == null) { uploader = new UploadService(manager); uploader.start(); } this.manager = manager; reloadDbHelper(manager); HandlerThread thread = new HandlerThread(getClass().getName()); thread.start(); this.looper = thread.getLooper(); this.handler = new Handler(looper); writeAction = new WriteDataAction(databaseHelper); writeAction.setHandler(handler); archiveAction = new RunArchiveAction(archive, databaseHelper); archiveAction.setHandler(handler); uploadAction = new RunUploadAction(archive, upload, uploader); uploadAction.setHandler(handler); updateAction = new RunUpdateAction(name, getFunfManager(), update); updateAction.setHandler(handler); handler.post(new Runnable() { @Override public void run() { setupDataSources(); } }); } @Override public void onRun(String action, JsonElement config) { // Run on handler thread if (ACTION_ARCHIVE.equals(action)) { archiveAction.run(); } else if (ACTION_UPLOAD.equals(action)) { uploadAction.run(); } else if (ACTION_UPDATE.equals(action)) { updateAction.run(); } } @Override public void onDestroy() { if (uploader != null) { uploader.stop(); } handler.post(new Runnable() { @Override public void run() { destroyDataSources(); looper.quit(); } }); } @Override public boolean isEnabled() { return enabled; } @Override public void onDataReceived(IJsonObject probeConfig, IJsonObject data) { writeAction.onDataReceived(probeConfig, data); } @Override public void onDataCompleted(IJsonObject probeConfig, JsonElement checkpoint) { writeAction.onDataCompleted(probeConfig, checkpoint); } public Handler getHandler() { return handler; } public FunfManager getFunfManager() { return manager; } protected void reloadDbHelper(Context ctx) { this.databaseHelper = new NameValueDatabaseHelper(ctx, StringUtil.simpleFilesafe(name), version); } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public FileArchive getArchive() { return archive; } public void setArchive(FileArchive archive) { this.archive = archive; } public RemoteFileArchive getUpload() { return upload; } public void setUpload(RemoteFileArchive upload) { this.upload = upload; } public ConfigUpdater getUpdate() { return update; } public void setUpdate(ConfigUpdater update) { this.update = update; } }