/*
* Geopaparazzi - Digital field mapping on Android based devices
* Copyright (C) 2013 HydroloGIS (www.hydrologis.com)
*
* 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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package eu.geopaparazzi.library.database;
import java.io.IOException;
import java.util.Date;
import java.util.Map.Entry;
import java.util.Set;
import eu.geopaparazzi.library.util.LibraryConstants;
import android.content.ContentValues;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
/**
* The class that handles logging to the database.
*
* @author Andrea Antonello (www.hydrologis.com)
*/
@SuppressWarnings("nls")
public class GPLog {
/**
* If <code>true</code>, android logging is activated.
*/
public final static boolean LOG_ANDROID = true;
/**
* If <code>true</code>, normal logging is activated.
*/
public static boolean LOG = true;
/**
* If <code>true</code> heavy logging is activated.
*/
public static boolean LOG_HEAVY = true;
/**
* If <code>true</code>, all logging is activated.
*/
public static boolean LOG_ABSURD = false;
public static final String ERROR_TAG = "ERROR";
public static final String TABLE_LOG = "log";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_DATAORA = "dataora";
public static final String COLUMN_LOGMSG = "logmsg";
/**
* Create the default log table.
*
* @param sqliteDatabase the db into which to create the table.
* @throws IOException
*/
public static void createTables( SQLiteDatabase sqliteDatabase ) throws IOException {
StringBuilder sB = new StringBuilder();
sB = new StringBuilder();
sB.append("CREATE TABLE ");
sB.append(TABLE_LOG);
sB.append(" (");
sB.append(COLUMN_ID);
sB.append(" INTEGER PRIMARY KEY AUTOINCREMENT, ");
sB.append(COLUMN_DATAORA).append(" INTEGER NOT NULL, ");
sB.append(COLUMN_LOGMSG).append(" TEXT ");
sB.append(");");
String CREATE_TABLE = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX " + TABLE_LOG + "_" + COLUMN_ID + " ON ");
sB.append(TABLE_LOG);
sB.append(" ( ");
sB.append(COLUMN_ID);
sB.append(" );");
String CREATE_INDEX = sB.toString();
sB = new StringBuilder();
sB.append("CREATE INDEX " + TABLE_LOG + "_" + COLUMN_DATAORA + " ON ");
sB.append(TABLE_LOG);
sB.append(" ( ");
sB.append(COLUMN_DATAORA);
sB.append(" );");
String CREATE_INDEX_DATE = sB.toString();
sqliteDatabase.beginTransaction();
try {
sqliteDatabase.execSQL(CREATE_TABLE);
sqliteDatabase.execSQL(CREATE_INDEX);
sqliteDatabase.execSQL(CREATE_INDEX_DATE);
sqliteDatabase.setTransactionSuccessful();
} catch (Exception e) {
throw new IOException(e.getLocalizedMessage());
} finally {
sqliteDatabase.endTransaction();
}
}
/**
* Add a new log entry.
*
* @param logMessage the message to insert in the log.
* @throws IOException
*/
public static void addLogEntry( String logMessage ) throws IOException {
SQLiteDatabase sqliteDatabase = ADbHelper.getInstance().getDatabase();
ContentValues values = new ContentValues();
Date date = new Date();
long time = date.getTime();
values.put(COLUMN_DATAORA, time);
values.put(COLUMN_LOGMSG, logMessage);
insertOrThrow(sqliteDatabase, TABLE_LOG, values);
if (LOG_ANDROID) {
StringBuilder sb = new StringBuilder();
sb.append(LibraryConstants.iso8601Format.format(date));
sb.append(": ");
sb.append(logMessage);
String string = sb.toString();
log("GPLOG", string);
}
}
private static int log( String tag, String string ) {
return Log.i(tag, string);
}
/**
* Add a log entry by concatenating (;) some more info in the message.
*
* @param caller the calling class or tage name.
* @param user a user name or id. If
* <code>null</code>, defaults to UNKNOWN_USER
* @param tag a tag for the log message. If <code>null</code>,
* defaults to INFO.
* @param logMessage the message itself.
*/
public static void addLogEntry( Object caller, //
String user, //
String tag,//
String logMessage ) {
StringBuilder sb = new StringBuilder();
if (user == null || user.length() == 0) {
user = "UU";
}
sb.append(user).append(";");
if (tag == null || tag.length() == 0) {
tag = "INFO";
}
sb.append(tag).append(";");
if (caller != null) {
String name = toName(caller);
if (name.length() > 0)
sb.append(name).append(": ");
}
sb.append(logMessage);
try {
addLogEntry(sb.toString());
} catch (IOException e) {
e.printStackTrace();
Log.e(ERROR_TAG, "Error inserting in log.", e);
}
}
/**
* Add a log entry by concatenating (;) some more info in the message.
*
* @param caller the calling class or tage name.
* @param logMessage the message itself.
*/
public static void addLogEntry( Object caller, //
String logMessage ) {
addLogEntry(caller, null, null, logMessage);
}
public static void error( Object caller, String msg, Throwable t ) {
String localizedMessage = t.getLocalizedMessage();
if (msg != null) {
StringBuilder sb = new StringBuilder();
sb.append(msg);
sb.append(": ");
sb.append(localizedMessage);
localizedMessage = sb.toString();
}
addLogEntry(caller, null, ERROR_TAG, localizedMessage);
if (LOG_ANDROID) {
log("GPLOG_ERROR", localizedMessage);
}
String stackTrace = Log.getStackTraceString(t);
addLogEntry(caller, null, ERROR_TAG, stackTrace);
if (LOG_ANDROID) {
log("GPLOG_ERROR", stackTrace);
}
}
/**
* Do an insert or throw with the proper error handling.
* @param table
* @param values
*
* @return
* @throws IOException
*/
private static long insertOrThrow( SQLiteDatabase sqliteDatabase, String table, ContentValues values ) throws IOException {
if (sqliteDatabase == null) {
throw new IOException("Database not ready!");
}
long id = sqliteDatabase.insertOrThrow(table, null, values);
if (id == -1) {
Set<Entry<String, Object>> valueSet = values.valueSet();
StringBuilder sb = new StringBuilder();
sb.append("Insert failed with: \n");
for( Entry<String, Object> entry : valueSet ) {
sb.append("(").append(entry.getKey()).append(",");
sb.append(entry.getValue()).append(")\n");
}
String message = sb.toString();
throw new IOException(message);
}
return id;
}
/**
* Clear the log table.
*
* @param db the db to use.
* @throws Exception
*/
public static void clearLogTable( SQLiteDatabase db ) throws Exception {
String deleteLogQuery = "delete from " + TABLE_LOG;
db.beginTransaction();
try {
db.execSQL(deleteLogQuery);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* @return the query to get id,datetimestring,logmsg.
*/
public static String getLogQuery() {
StringBuilder sb = new StringBuilder();
sb.append("select _id, datetime(dataora/1000, 'unixepoch', 'localtime') as timestamp, logmsg from log order by dataora desc");
String query = sb.toString();
return query;
}
private static String toName( Object obj ) {
if (obj instanceof String) {
String name = (String) obj;
return name;
}
String simpleName = obj.getClass().getSimpleName();
return simpleName.toUpperCase();
}
}