use of org.odk.collect.android.exception.ExternalDataException in project collect by opendatakit.
the class ExternalDataHandlerSearch method eval.
@Override
public Object eval(Object[] args, EvaluationContext ec) {
if (args == null || (args.length != 1 && args.length != 4 && args.length != 6)) {
// .getSearchXPathExpression(String appearance)
throw new ExternalDataException(Collect.getInstance().getString(R.string.ext_search_wrong_arguments_error));
}
String searchType = null;
String queriedColumnsParam = null;
List<String> queriedColumns = null;
String queriedValue = null;
if (args.length >= 4) {
searchType = XPathFuncExpr.toString(args[1]);
queriedColumnsParam = XPathFuncExpr.toString(args[2]);
queriedValue = XPathFuncExpr.toString(args[3]);
}
ExternalDataSearchType externalDataSearchType = ExternalDataSearchType.getByKeyword(searchType, ExternalDataSearchType.CONTAINS);
boolean searchRows = false;
boolean useFilter = false;
if (queriedColumnsParam != null && queriedColumnsParam.trim().length() > 0) {
searchRows = true;
queriedColumns = ExternalDataUtil.createListOfColumns(queriedColumnsParam);
}
String filterColumn = null;
String filterValue = null;
if (args.length == 6) {
filterColumn = XPathFuncExpr.toString(args[4]);
filterValue = XPathFuncExpr.toString(args[5]);
useFilter = true;
}
// SCTO-545
String dataSetName = normalize(XPathFuncExpr.toString(args[0]));
Cursor c = null;
try {
ExternalSQLiteOpenHelper sqLiteOpenHelper = getExternalDataManager().getDatabase(dataSetName, true);
SQLiteDatabase db = sqLiteOpenHelper.getReadableDatabase();
LinkedHashMap<String, String> selectColumnMap = ExternalDataUtil.createMapWithDisplayingColumns(getValueColumn(), getDisplayColumns());
List<String> columnsToFetch = new ArrayList<String>(selectColumnMap.keySet());
String safeImageColumn = null;
if (getImageColumn() != null && getImageColumn().trim().length() > 0) {
safeImageColumn = ExternalDataUtil.toSafeColumnName(getImageColumn());
columnsToFetch.add(safeImageColumn);
}
String[] sqlColumns = columnsToFetch.toArray(new String[columnsToFetch.size()]);
String selection;
String[] selectionArgs;
if (searchRows && useFilter) {
selection = "( " + createLikeExpression(queriedColumns) + " ) AND " + ExternalDataUtil.toSafeColumnName(filterColumn) + "=? ";
String[] likeArgs = externalDataSearchType.constructLikeArguments(queriedValue, queriedColumns.size());
selectionArgs = new String[likeArgs.length + 1];
System.arraycopy(likeArgs, 0, selectionArgs, 0, likeArgs.length);
selectionArgs[selectionArgs.length - 1] = filterValue;
} else if (searchRows) {
selection = createLikeExpression(queriedColumns);
selectionArgs = externalDataSearchType.constructLikeArguments(queriedValue, queriedColumns.size());
} else if (useFilter) {
selection = ExternalDataUtil.toSafeColumnName(filterColumn) + "=? ";
selectionArgs = new String[] { filterValue };
} else {
selection = null;
selectionArgs = null;
}
try {
c = db.query(ExternalDataUtil.EXTERNAL_DATA_TABLE_NAME, sqlColumns, selection, selectionArgs, null, null, ExternalDataUtil.SORT_COLUMN_NAME);
} catch (Exception e) {
if (c != null) {
c.close();
}
c = db.query(ExternalDataUtil.EXTERNAL_DATA_TABLE_NAME, sqlColumns, selection, selectionArgs, null, null, null);
}
return createDynamicSelectChoices(c, selectColumnMap, safeImageColumn);
} finally {
if (c != null) {
c.close();
}
}
}
use of org.odk.collect.android.exception.ExternalDataException in project collect by opendatakit.
the class ExternalDataManagerImpl method getDatabase.
@Override
public ExternalSQLiteOpenHelper getDatabase(String dataSetName, boolean required) {
ExternalSQLiteOpenHelper sqLiteOpenHelper = dbMap.get(dataSetName);
if (sqLiteOpenHelper == null) {
if (mediaFolder == null) {
String msg = Collect.getInstance().getString(R.string.ext_not_initialized_error);
Timber.e(msg);
if (required) {
throw new ExternalDataException(msg);
} else {
return null;
}
} else {
File dbFile = new File(mediaFolder, dataSetName + ".db");
if (!dbFile.exists()) {
String msg = Collect.getInstance().getString(R.string.ext_import_csv_missing_error, dataSetName, dataSetName);
Timber.e(msg);
if (required) {
throw new ExternalDataException(msg);
} else {
return null;
}
} else {
sqLiteOpenHelper = new ExternalSQLiteOpenHelper(dbFile);
dbMap.put(dataSetName, sqLiteOpenHelper);
}
}
}
return sqLiteOpenHelper;
}
use of org.odk.collect.android.exception.ExternalDataException in project collect by opendatakit.
the class ExternalDataUtil method populateExternalChoices.
public static ArrayList<SelectChoice> populateExternalChoices(FormEntryPrompt formEntryPrompt, XPathFuncExpr xpathfuncexpr) {
try {
List<SelectChoice> selectChoices = formEntryPrompt.getSelectChoices();
ArrayList<SelectChoice> returnedChoices = new ArrayList<SelectChoice>();
for (SelectChoice selectChoice : selectChoices) {
String value = selectChoice.getValue();
if (isAnInteger(value)) {
// treat this as a static choice
returnedChoices.add(selectChoice);
} else {
String displayColumns = formEntryPrompt.getSelectChoiceText(selectChoice);
String imageColumn = formEntryPrompt.getSpecialFormSelectChoiceText(selectChoice, FormEntryCaption.TEXT_FORM_IMAGE);
if (imageColumn != null && imageColumn.startsWith(JR_IMAGES_PREFIX)) {
imageColumn = imageColumn.substring(JR_IMAGES_PREFIX.length());
}
// if (displayColumns == null || displayColumns.trim().length() == 0) {
// throw new InvalidSyntaxException("The label column in the choices sheet
// appears to be empty (or has been calculated as empty).");
// }
ExternalDataManager externalDataManager = Collect.getInstance().getExternalDataManager();
FormInstance formInstance = Collect.getInstance().getFormController().getFormDef().getInstance();
EvaluationContext baseEvaluationContext = new EvaluationContext(formInstance);
EvaluationContext evaluationContext = new EvaluationContext(baseEvaluationContext, formEntryPrompt.getIndex().getReference());
// we can only add only the appropriate by querying the xPathFuncExpr.id.name
evaluationContext.addFunctionHandler(new ExternalDataHandlerSearch(externalDataManager, displayColumns, value, imageColumn));
Object eval = xpathfuncexpr.eval(formInstance, evaluationContext);
if (eval.getClass().isAssignableFrom(ArrayList.class)) {
@SuppressWarnings("unchecked") List<SelectChoice> dynamicChoices = (ArrayList<SelectChoice>) eval;
for (SelectChoice dynamicChoice : dynamicChoices) {
returnedChoices.add(dynamicChoice);
}
} else {
throw new ExternalDataException(Collect.getInstance().getString(R.string.ext_search_return_error, eval.getClass().getName()));
}
}
}
return returnedChoices;
} catch (Exception e) {
throw new ExternalDataException(e.getMessage(), e);
}
}
use of org.odk.collect.android.exception.ExternalDataException in project collect by opendatakit.
the class ExternalSQLiteOpenHelper method onCreateNamed.
private void onCreateNamed(SQLiteDatabase db, String tableName) throws Exception {
Timber.w("Reading data from '%s", dataSetFile.toString());
onProgress(Collect.getInstance().getString(R.string.ext_import_progress_message, dataSetFile.getName(), ""));
CSVReader reader = null;
try {
reader = new CSVReader(new InputStreamReader(new FileInputStream(dataSetFile), "UTF-8"), DELIMITING_CHAR, QUOTE_CHAR, ESCAPE_CHAR);
String[] headerRow = reader.readNext();
if (!ExternalDataUtil.containsAnyData(headerRow)) {
throw new ExternalDataException(Collect.getInstance().getString(R.string.ext_file_no_data_error));
}
List<String> conflictingColumns = ExternalDataUtil.findMatchingColumnsAfterSafeningNames(headerRow);
if (conflictingColumns != null && conflictingColumns.size() > 0) {
// so the create table query will fail with "duplicate column" error.
throw new ExternalDataException(Collect.getInstance().getString(R.string.ext_conflicting_columns_error, conflictingColumns));
}
Map<String, String> columnNamesCache = new HashMap<String, String>();
StringBuilder sb = new StringBuilder();
boolean sortColumnAlreadyPresent = false;
sb.append("CREATE TABLE ");
sb.append(tableName);
sb.append(" ( ");
for (int i = 0; i < headerRow.length; i++) {
String columnName = headerRow[i].trim();
if (columnName.length() == 0) {
continue;
}
if (i != 0) {
sb.append(", ");
}
String safeColumnName = ExternalDataUtil.toSafeColumnName(columnName, columnNamesCache);
if (safeColumnName.equals(ExternalDataUtil.SORT_COLUMN_NAME)) {
sortColumnAlreadyPresent = true;
sb.append(safeColumnName).append(" real ");
} else {
sb.append(safeColumnName).append(" text collate nocase ");
}
}
if (!sortColumnAlreadyPresent) {
sb.append(", ");
sb.append(ExternalDataUtil.SORT_COLUMN_NAME).append(" real ");
}
sb.append(" );");
String sql = sb.toString();
Timber.w("Creating database for %s with query: %s", dataSetFile, sql);
db.execSQL(sql);
// create the indexes.
// save the sql for later because inserts will be much faster if we don't have
// indexes already.
List<String> createIndexesCommands = new ArrayList<String>();
for (String header : headerRow) {
if (header.endsWith("_key")) {
String indexSQL = "CREATE INDEX " + header + "_idx ON " + tableName + " (" + ExternalDataUtil.toSafeColumnName(header, columnNamesCache) + ");";
createIndexesCommands.add(indexSQL);
Timber.w("Will create an index on %s later.", header);
}
}
// populate the database
String[] row = reader.readNext();
int rowCount = 0;
while (row != null && !formLoaderTask.isCancelled()) {
// SCTO-894 - first we should make sure that this is not an empty line
if (!ExternalDataUtil.containsAnyData(row)) {
// yes, that is an empty row, ignore it
row = reader.readNext();
continue;
}
// we will just fill up the rest with empty strings
if (row.length < headerRow.length) {
row = ExternalDataUtil.fillUpNullValues(row, headerRow);
}
ContentValues values = new ContentValues();
if (!sortColumnAlreadyPresent) {
values.put(ExternalDataUtil.SORT_COLUMN_NAME, rowCount + 1);
}
for (int i = 0; i < row.length && i < headerRow.length; i++) {
String columnName = headerRow[i].trim();
String columnValue = row[i];
if (columnName.length() == 0) {
continue;
}
String safeColumnName = ExternalDataUtil.toSafeColumnName(columnName, columnNamesCache);
if (safeColumnName.equals(ExternalDataUtil.SORT_COLUMN_NAME)) {
try {
values.put(safeColumnName, Double.parseDouble(columnValue));
} catch (NumberFormatException e) {
throw new ExternalDataException(Collect.getInstance().getString(R.string.ext_sortBy_numeric_error, columnValue));
}
} else {
values.put(safeColumnName, columnValue);
}
}
db.insertOrThrow(tableName, null, values);
row = reader.readNext();
rowCount++;
if (rowCount % 100 == 0) {
onProgress(Collect.getInstance().getString(R.string.ext_import_progress_message, dataSetFile.getName(), " (" + rowCount + " records so far)"));
}
}
if (formLoaderTask.isCancelled()) {
Timber.w("User canceled reading data from %s", dataSetFile.toString());
onProgress(Collect.getInstance().getString(R.string.ext_import_cancelled_message));
} else {
onProgress(Collect.getInstance().getString(R.string.ext_import_finalizing_message));
// now create the indexes
for (String createIndexCommand : createIndexesCommands) {
Timber.w(createIndexCommand);
db.execSQL(createIndexCommand);
}
Timber.w("Read all data from %s", dataSetFile.toString());
onProgress(Collect.getInstance().getString(R.string.ext_import_completed_message));
}
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
Timber.e(e);
}
}
}
}
Aggregations