<commit_before>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2009, Nokia
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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 Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <locale.h>

#include <glib.h>
#include <glib/gi18n.h>

#include <libtracker-client/tracker.h>
#include <libtracker-common/tracker-common.h>

static gint	      limit = 512;
static gint	      offset;
static gchar	    **terms;
static gboolean       or_operator;
static gboolean       detailed;
static gboolean       files;
static gboolean       folders;
static gboolean       music_albums;
static gboolean       music_artists;
static gboolean       music_files;
static gboolean       image_files;
static gboolean       video_files;
static gboolean       document_files;

static GOptionEntry   entries[] = {
	{ "limit", 'l', 0, G_OPTION_ARG_INT, &limit,
	  N_("Limit the number of results shown"),
	  N_("512")
	},
	{ "offset", 'o', 0, G_OPTION_ARG_INT, &offset,
	  N_("Offset the results"),
	  N_("0")
	},
	{ "or-operator", 'r', 0, G_OPTION_ARG_NONE, &or_operator,
	  N_("Use OR for search terms instead of AND (the default)"),
	  NULL
	},
	{ "detailed", 'd', 0, G_OPTION_ARG_NONE, &detailed,
	  N_("Show more detailed results (only applies to general search)"),
	  NULL
	},
	{ "files", 'f', 0, G_OPTION_ARG_NONE, &files,
	  N_("Search for files"),
	  NULL
	},
	{ "folders", 'e', 0, G_OPTION_ARG_NONE, &folders,
	  N_("Search for folders"),
	  NULL
	},
	{ "music-albums", 'a', 0, G_OPTION_ARG_NONE, &music_albums,
	  N_("Search for music albums (includes song count and duration sum)"),
	  NULL
	},
	{ "music-artists", 's', 0, G_OPTION_ARG_NONE, &music_artists,
	  N_("Search for music artists"),
	  NULL
	},
	{ "music", 'u', 0, G_OPTION_ARG_NONE, &music_files,
	  N_("Search for music files"),
	  NULL
	},
	{ "images", 'i', 0, G_OPTION_ARG_NONE, &image_files,
	  N_("Search for image files"),
	  NULL
	},
	{ "videos", 'v', 0, G_OPTION_ARG_NONE, &video_files,
	  N_("Search for video files"),
	  NULL
	},
	{ "documents", 't', 0, G_OPTION_ARG_NONE, &document_files,
	  N_("Search for document files"),
	  NULL
	},
	{ G_OPTION_REMAINING, 0, 0,
	  G_OPTION_ARG_STRING_ARRAY, &terms,
	  N_("search terms"),
	  N_("EXPRESSION")
	},
	{ NULL }
};

static void
show_limit_warning (void)
{
	/* Display '...' so the user thinks there is
	 * more items.
	 */
	g_print ("  ...\n");
	
	/* Display warning so the user knows this is
	 * not the WHOLE data set.
	 */
	g_printerr ("\n%s\n",
		    _("NOTE: Limit was reached, there are more items in the database not listed here"));
}

static gchar *
get_fts_string (GStrv    search_words,
		gboolean use_or_operator)
{
	GString *fts;
	gint i, len;

	if (!search_words) {
		return NULL;
	}

	fts = g_string_new ("");
	len = g_strv_length (search_words);

	for (i = 0; i < len; i++) {
		g_string_append (fts, search_words[i]);
		g_string_append_c (fts, '*');

		if (i < len - 1) { 
			if (use_or_operator) {
				g_string_append (fts, " OR ");
			} else {
				g_string_append (fts, " ");
			}
		}
	}

	return g_string_free (fts, FALSE);
}

static void
get_files_foreach (gpointer value,
		   gpointer user_data)
{
	gchar **data = value;

	g_print ("  %s\n", data[0]);
}

static gboolean
get_files_results (TrackerClient *client,
		   const gchar   *query,
		   gint           search_limit)
{
	GError *error = NULL;
	GPtrArray *results;

	results = tracker_resources_sparql_query (client, query, &error);

	if (error) {
		g_printerr ("%s, %s\n",
			    _("Could not get search results"),
			    error->message);
		g_error_free (error);

		return FALSE;
	}

	if (!results) {
		g_print ("%s\n",
			 _("No files were found"));
	} else {
		g_print (tracker_dngettext (NULL,
					    _("File: %d"), 
					    _("Files: %d"),
					    results->len),
			 results->len);
		g_print ("\n");

		g_ptr_array_foreach (results, 
				     get_files_foreach, 
				     NULL);

		if (results->len >= search_limit) {
			show_limit_warning ();
		}

		g_ptr_array_foreach (results, (GFunc) g_strfreev, NULL);
		g_ptr_array_free (results, TRUE);
	}

	return TRUE;
}

static gboolean
get_document_files (TrackerClient *client,
		    GStrv          search_terms,
		    gint           search_offset,
		    gint           search_limit,
		    gboolean       use_or_operator)
{
	gchar *fts;
	gchar *query;
	gboolean success;

	fts = get_fts_string (search_terms, use_or_operator);

	if (fts) {
		query = g_strdup_printf ("SELECT ?document "
					 "WHERE { "
					 "  ?document a nfo:PaginatedTextDocument ."
					 "  ?document fts:match \"%s\" "
					 "} "
					 "ORDER BY ASC(?document) "
					 "OFFSET %d "
					 "LIMIT %d",
					 fts,
					 search_offset, 
					 search_limit);
	} else {
		query = g_strdup_printf ("SELECT ?document "
					 "WHERE { "
					 "  ?document a nfo:PaginatedTextDocument "
					 "} "
					 "ORDER BY ASC(?document) "
					 "OFFSET %d "
					 "LIMIT %d",
					 search_offset, 
					 search_limit);
	}

	success = get_files_results (client, query, search_limit);
	g_free (query);
	g_free (fts);

	return success;
}

static gboolean<commit_msg>tracker-search: Use nfo:Document instead of nfo:PaginatedDocument<commit_after>/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Copyright (C) 2009, Nokia
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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 Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA  02110-1301, USA.
 */

#include "config.h"

#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <locale.h>

#include <glib.h>
#include <glib/gi18n.h>

#include <libtracker-client/tracker.h>
#include <libtracker-common/tracker-common.h>

static gint	      limit = 512;
static gint	      offset;
static gchar	    **terms;
static gboolean       or_operator;
static gboolean       detailed;
static gboolean       files;
static gboolean       folders;
static gboolean       music_albums;
static gboolean       music_artists;
static gboolean       music_files;
static gboolean       image_files;
static gboolean       video_files;
static gboolean       document_files;

static GOptionEntry   entries[] = {
	{ "limit", 'l', 0, G_OPTION_ARG_INT, &limit,
	  N_("Limit the number of results shown"),
	  N_("512")
	},
	{ "offset", 'o', 0, G_OPTION_ARG_INT, &offset,
	  N_("Offset the results"),
	  N_("0")
	},
	{ "or-operator", 'r', 0, G_OPTION_ARG_NONE, &or_operator,
	  N_("Use OR for search terms instead of AND (the default)"),
	  NULL
	},
	{ "detailed", 'd', 0, G_OPTION_ARG_NONE, &detailed,
	  N_("Show more detailed results (only applies to general search)"),
	  NULL
	},
	{ "files", 'f', 0, G_OPTION_ARG_NONE, &files,
	  N_("Search for files"),
	  NULL
	},
	{ "folders", 'e', 0, G_OPTION_ARG_NONE, &folders,
	  N_("Search for folders"),
	  NULL
	},
	{ "music-albums", 'a', 0, G_OPTION_ARG_NONE, &music_albums,
	  N_("Search for music albums (includes song count and duration sum)"),
	  NULL
	},
	{ "music-artists", 's', 0, G_OPTION_ARG_NONE, &music_artists,
	  N_("Search for music artists"),
	  NULL
	},
	{ "music", 'u', 0, G_OPTION_ARG_NONE, &music_files,
	  N_("Search for music files"),
	  NULL
	},
	{ "images", 'i', 0, G_OPTION_ARG_NONE, &image_files,
	  N_("Search for image files"),
	  NULL
	},
	{ "videos", 'v', 0, G_OPTION_ARG_NONE, &video_files,
	  N_("Search for video files"),
	  NULL
	},
	{ "documents", 't', 0, G_OPTION_ARG_NONE, &document_files,
	  N_("Search for document files"),
	  NULL
	},
	{ G_OPTION_REMAINING, 0, 0,
	  G_OPTION_ARG_STRING_ARRAY, &terms,
	  N_("search terms"),
	  N_("EXPRESSION")
	},
	{ NULL }
};

static void
show_limit_warning (void)
{
	/* Display '...' so the user thinks there is
	 * more items.
	 */
	g_print ("  ...\n");
	
	/* Display warning so the user knows this is
	 * not the WHOLE data set.
	 */
	g_printerr ("\n%s\n",
		    _("NOTE: Limit was reached, there are more items in the database not listed here"));
}

static gchar *
get_fts_string (GStrv    search_words,
		gboolean use_or_operator)
{
	GString *fts;
	gint i, len;

	if (!search_words) {
		return NULL;
	}

	fts = g_string_new ("");
	len = g_strv_length (search_words);

	for (i = 0; i < len; i++) {
		g_string_append (fts, search_words[i]);
		g_string_append_c (fts, '*');

		if (i < len - 1) { 
			if (use_or_operator) {
				g_string_append (fts, " OR ");
			} else {
				g_string_append (fts, " ");
			}
		}
	}

	return g_string_free (fts, FALSE);
}

static void
get_files_foreach (gpointer value,
		   gpointer user_data)
{
	gchar **data = value;

	g_print ("  %s\n", data[0]);
}

static gboolean
get_files_results (TrackerClient *client,
		   const gchar   *query,
		   gint           search_limit)
{
	GError *error = NULL;
	GPtrArray *results;

	results = tracker_resources_sparql_query (client, query, &error);

	if (error) {
		g_printerr ("%s, %s\n",
			    _("Could not get search results"),
			    error->message);
		g_error_free (error);

		return FALSE;
	}

	if (!results) {
		g_print ("%s\n",
			 _("No files were found"));
	} else {
		g_print (tracker_dngettext (NULL,
					    _("File: %d"), 
					    _("Files: %d"),
					    results->len),
			 results->len);
		g_print ("\n");

		g_ptr_array_foreach (results, 
				     get_files_foreach, 
				     NULL);

		if (results->len >= search_limit) {
			show_limit_warning ();
		}

		g_ptr_array_foreach (results, (GFunc) g_strfreev, NULL);
		g_ptr_array_free (results, TRUE);
	}

	return TRUE;
}

static gboolean
get_document_files (TrackerClient *client,
		    GStrv          search_terms,
		    gint           search_offset,
		    gint           search_limit,
		    gboolean       use_or_operator)
{
	gchar *fts;
	gchar *query;
	gboolean success;

	fts = get_fts_string (search_terms, use_or_operator);

	if (fts) {
		query = g_strdup_printf ("SELECT ?document "
					 "WHERE { "
					 "  ?document a nfo:Document ."
					 "  ?document fts:match \"%s\" "
					 "} "
					 "ORDER BY ASC(?document) "
					 "OFFSET %d "
					 "LIMIT %d",
					 fts,
					 search_offset, 
					 search_limit);
	} else {
		query = g_strdup_printf ("SELECT ?document "
					 "WHERE { "
					 "  ?document a nfo:Document "
					 "} "
					 "ORDER BY ASC(?document) "
					 "OFFSET %d "
					 "LIMIT %d",
					 search_offset, 
					 search_limit);
	}

	success = get_files_results (client, query, search_limit);
	g_free (query);
	g_free (fts);

	return success;
}

static gboolean
{'fraction_non_alphanumeric': 0.13045711350796096, 'fraction_numerical': 0.007532956685499058, 'mean_word_length': 3.138505136379738, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3204290', 'n_tokens_mistral': 4654, 'n_tokens_neox': 4084, 'n_words': 1182}