Android Open Source - classy_apps Classy Fy Search Engine






From Project

Back to project page classy_apps.

License

The source code is released under:

GNU General Public License

If you think the Android project classy_apps listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/**
    Copyright (C) 2014  www.cybersearch2.com.au
//from www .ja  v a 2s .  c om
    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 au.com.cybersearch2.classyfy.provider;

import java.util.HashMap;
import java.util.Map;

import android.app.SearchManager;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.provider.BaseColumns;
import android.text.TextUtils;
import au.com.cybersearch2.classyfts.FtsEngine;
import au.com.cybersearch2.classyfts.FtsOpenHelper;
import au.com.cybersearch2.classyfts.FtsQueryBuilder;
import au.com.cybersearch2.classyfts.SearchEngineBase;
import au.com.cybersearch2.classyfts.WordFilter;
import au.com.cybersearch2.classyfy.R;

/**
 * ClassyFySearchEngine
 * @author Andrew Bowley
 * 11/07/2014
 */
public class ClassyFySearchEngine extends SearchEngineBase
{
    
    public static final String PROVIDER_AUTHORITY = "au.com.cybersearch2.classyfy.ClassyFyProvider";
    public static final Uri CONTENT_URI = Uri.parse("content://au.com.cybersearch2.classyfy.ClassyFyProvider/all_nodes");
    public static Uri LEX_CONTENT_URI = Uri.parse("content://" + PROVIDER_AUTHORITY + "/" + LEX + "/" + SearchManager.SUGGEST_URI_PATH_QUERY);
    public static final String ALL_NODES_VIEW = "all_nodes";
    
    // Column names
    // Android expects RowIDColumn to be "_id", so do not use any other value.
    public static final String KEY_ID = "_id";
    public static final String KEY_NAME = "name";
    public static final String KEY_TITLE = "title";
    public static final String KEY_MODEL = "model";

    // Create the constants used to differntiate between the different URI requests
    // Note values 1 - 4 are reserved for 
    // SEARCH_SUGGEST, REFRESH_SHORTCUT, LEXICAL_SEARCH_SUGGEST and LEXICAL_REFRESH_SHORTCUT
    protected static final int ALL_NODES_TYPES = PROVIDER_TYPE;
    protected static final int ALL_NODES_TYPE_ID = ALL_NODES_TYPES + 1;

    
    protected final UriMatcher uriMatcher;
    protected SQLiteOpenHelper sqLiteOpenHelper;
    
    // Search suggestions support. A Cursor must be returned with a set of pre-defined columns
    protected final Map<String, String> ALL_NODES_TYPE_SEARCH_PROJECTION_MAP;
    

    public ClassyFySearchEngine()
    {
        super();
        uriMatcher = createUriMatcher();
        ALL_NODES_TYPE_SEARCH_PROJECTION_MAP = createProjectionMap();
    }

    @Override
    public void onCreate(SQLiteOpenHelper sqLiteOpenHelper)
    {
        this.sqLiteOpenHelper = sqLiteOpenHelper;
        WordFilter text2Filter = new WordFilter(){
            /**
             * Search result word filter 
             * @param key Database column name 
             * @param word Word from column identified by the key
             * @return Same value as "word" parameter or a replacement value
             */
            @Override
            public String filter(String key, String word) {
                if ("model".equals(key))
                    return word.replace("record", "");
                else
                    return word;
            }
        };
        Map<String,String> COLUMN_MAP = new HashMap<String,String>();
        COLUMN_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_1, "title");
        COLUMN_MAP.put(SearchManager.SUGGEST_COLUMN_TEXT_2, "model");
        COLUMN_MAP.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, "_id");
        FtsOpenHelper ftsOpenHelper = new FtsOpenHelper(sqLiteOpenHelper);
        FtsEngine ftsEngine = new FtsEngine(ftsOpenHelper, "all_nodes", COLUMN_MAP);
        ftsEngine.setOrderbyText2(true);
        ftsEngine.setText2Filter(text2Filter);
        if (LEX.equals(getSearchSuggestPath(R.xml.searchable))) 
            startFtsEngine(ftsEngine);
    }

    /**
     * This is called when a client calls {@link android.content.ContentResolver#getType(Uri)}.
     * Returns the "custom" or "vendor-specific" MIME data type of the URI given as a parameter.
     * MIME types have the format "type/subtype". The type value is always "vnd.android.cursor.dir"
     * for multiple rows, or "vnd.android.cursor.item" for a single row. 
     *
     * @param uri The URI whose MIME type is desired.
     * @return The MIME type of the URI.
     * @throws IllegalArgumentException if the incoming URI pattern is invalid.
     */
 
     public String getType(Uri uri)
     {
         int queryType = uriMatcher.match(uri);
         switch (queryType)
         {
         case ALL_NODES_TYPES: 
             return "vnd.android.cursor.dir/vnd.classyfy.node";
         case ALL_NODES_TYPE_ID: 
             return "vnd.android.cursor.item/vnd.classyfy.node";
         default: 
             return super.getType(queryType, uri);
         }
     }


    public Cursor query(Uri uri, final String[] projection, final String selection,
            final String[] selectionArgs, final String sortOrder)
    {
        final int queryType = uriMatcher.match(uri);
        FtsQueryBuilder qb = new FtsQueryBuilder(
                queryType, 
                uri, 
                projection, 
                selection,
                selectionArgs, 
                sortOrder);
        return query(uri, qb);
    }
    
    
    protected Cursor query(Uri uri, FtsQueryBuilder qb)
    {
        qb.setTables(ALL_NODES_VIEW);
        // If this is a row query then limit the result set to the passed in row
        switch (qb.getQueryType())
        {
        case ALL_NODES_TYPE_ID: 
            if (uri.getPathSegments().size() < 2)
                throw new IllegalArgumentException("Invalid quiery Uri: " + uri.toString());
            qb.appendWhere(KEY_ID + "=" + uri.getPathSegments().get(1)); 
            break;
        case ALL_NODES_TYPES:
            break; 
        case LEXICAL_SEARCH_SUGGEST: // Fall back if Fts not available
        case SEARCH_SUGGEST:         // Search Suggestions support query appended with: where title like "%<search-term>%" Note: uri can have /?limit=50
        {
            qb.appendWhere(KEY_TITLE + " like \"%" + qb.getSearchTerm() + "%\"");
            qb.setProjectionMap(ALL_NODES_TYPE_SEARCH_PROJECTION_MAP);
            break;
        }          
        case REFRESH_SHORTCUT:
        case LEXICAL_REFRESH_SHORTCUT:
           // TODO
            break;
        default: break;
        }
        // If no sort order is specified, sort by title
        if (TextUtils.isEmpty(qb.getSortOrder()))
            qb.setSortOrder(KEY_NAME + " ASC");
        // Apply the query to the underlying database
        return query(qb, sqLiteOpenHelper);
    }

    /* (non-Javadoc)
     * @see android.content.ContentProvider#insert(android.net.Uri, android.content.ContentValues)
     */
    public Uri insert(Uri uri, ContentValues values)
    {
        SQLiteDatabase database = sqLiteOpenHelper.getWritableDatabase();
        // Insert the new row. The call to database.insert will return the row number if it is successful
        long rowId = database.insert(ALL_NODES_VIEW, null, values);
        // Return a URI to the newly inserted row on success
        if (rowId > 0)
        {
            Uri resultUri = ContentUris.withAppendedId(CONTENT_URI, rowId);
            notifyChange(resultUri);
            return resultUri;
        }
        throw new SQLException("Failed to insert row into " + uri);
    }

    /* (non-Javadoc)
     * @see android.content.ContentProvider#delete(android.net.Uri, java.lang.String, java.lang.String[])
     */
    public int delete(Uri uri, String selection, String[] selectionArgs)
    {
        SQLiteDatabase database = sqLiteOpenHelper.getWritableDatabase();
        int count;
        switch (uriMatcher.match(uri))
        {
        case ALL_NODES_TYPES: 
            count = database.delete(ALL_NODES_VIEW, selection, selectionArgs);
            break;
        case ALL_NODES_TYPE_ID:
            String segment = uri.getPathSegments().get(1);
            String rowSelection = (!TextUtils.isEmpty(selection) ? " and (" + selection + ')' : "");
            count = database.delete(ALL_NODES_VIEW, KEY_ID + "=" + segment + rowSelection, selectionArgs);
            break;
        default: throw new IllegalArgumentException("Unsupported URI: " + uri);
            
        }
        notifyChange(uri);
        return count;
    }

    /* (non-Javadoc)
     * @see android.content.ContentProvider#update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[])
     */
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs)
    {
        SQLiteDatabase database = sqLiteOpenHelper.getWritableDatabase();
        int count;
        switch (uriMatcher.match(uri))
        {
        case ALL_NODES_TYPES: 
            count = database.update(ALL_NODES_VIEW, values, selection, selectionArgs);
            break;
        case ALL_NODES_TYPE_ID:
            String segment = uri.getPathSegments().get(1);
            String rowSelection = (!TextUtils.isEmpty(selection) ? " and (" + selection + ')' : "");
            count = database.update(ALL_NODES_VIEW, values,
                    KEY_ID + "=" + segment + rowSelection, selectionArgs);
            break;
        default: throw new IllegalArgumentException("Unknown URI " + uri);
            
        }
        notifyChange(uri);
        return count;
    }

    protected static UriMatcher createUriMatcher() 
    {
        // Allocate the UriMatcher object where a URI ending is 'all_nodes' will correspond to a request for all nodes, 
        // and 'all_nodes' with a trailing '/[rowID]' will represent a single all_nodes row

        UriMatcher newUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, "all_nodes", ALL_NODES_TYPES);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, "all_nodes/#", ALL_NODES_TYPE_ID);
        // to get suggestions...
        newUriMatcher.addURI(PROVIDER_AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, LEX + "/" + SearchManager.SUGGEST_URI_PATH_QUERY, LEXICAL_SEARCH_SUGGEST);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, LEX + "/" + SearchManager.SUGGEST_URI_PATH_QUERY + "/*", LEXICAL_SEARCH_SUGGEST);
        /* The following are unused in this implementation, but if we include
         * {@link SearchManager#SUGGEST_COLUMN_SHORTCUT_ID} as a column in our suggestions table, we
         * could expect to receive refresh queries when a shortcutted suggestion is displayed in
         * Quick Search Box, in which case, the following Uris would be provided and we
         * would return a cursor with a single item representing the refreshed suggestion data.
         */
        newUriMatcher.addURI(PROVIDER_AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT, REFRESH_SHORTCUT);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", REFRESH_SHORTCUT);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, LEX + "/" + SearchManager.SUGGEST_URI_PATH_SHORTCUT, LEXICAL_REFRESH_SHORTCUT);
        newUriMatcher.addURI(PROVIDER_AUTHORITY, LEX + "/" + SearchManager.SUGGEST_URI_PATH_SHORTCUT + "/*", LEXICAL_REFRESH_SHORTCUT);
        return newUriMatcher;
    }

    protected static Map<String, String> createProjectionMap() 
    {
        Map<String, String> newProjectionMap = new HashMap<String, String>();
        newProjectionMap.put(BaseColumns._ID, 
                KEY_ID + " as " + BaseColumns._ID);
        newProjectionMap.put(SearchManager.SUGGEST_COLUMN_TEXT_1, 
                KEY_TITLE + " as " + SearchManager.SUGGEST_COLUMN_TEXT_1);
        newProjectionMap.put(SearchManager.SUGGEST_COLUMN_TEXT_2, 
                KEY_MODEL + " as " + SearchManager.SUGGEST_COLUMN_TEXT_2);
        newProjectionMap.put(SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID, 
                KEY_ID + " AS " + SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID);
        return newProjectionMap;
    }



}




Java Source Code List

au.com.cybersearch2.classyfy.ClassyFyApplicationModule.java
au.com.cybersearch2.classyfy.ClassyFyApplication.java
au.com.cybersearch2.classyfy.ClassyFyEnvironmentModule.java
au.com.cybersearch2.classyfy.ClassyFyResourceEnvironment.java
au.com.cybersearch2.classyfy.ClassyFyStartup.java
au.com.cybersearch2.classyfy.ClassyFyThreadHelper.java
au.com.cybersearch2.classyfy.MainActivityTest.java
au.com.cybersearch2.classyfy.MainActivity.java
au.com.cybersearch2.classyfy.NodeDetailsDialog.java
au.com.cybersearch2.classyfy.NodeDetailsFragment.java
au.com.cybersearch2.classyfy.ProgressFragment.java
au.com.cybersearch2.classyfy.TitleSearchResultsActivityTest.java
au.com.cybersearch2.classyfy.TitleSearchResultsActivity.java
au.com.cybersearch2.classyfy.TitleSearchResultsFragment.java
au.com.cybersearch2.classyfy.data.DataLoader.java
au.com.cybersearch2.classyfy.data.DataStreamParser.java
au.com.cybersearch2.classyfy.data.FieldDescriptor.java
au.com.cybersearch2.classyfy.data.FilePlanNodeType.java
au.com.cybersearch2.classyfy.data.ManagedRecord.java
au.com.cybersearch2.classyfy.data.Model.java
au.com.cybersearch2.classyfy.data.RecordCategory.java
au.com.cybersearch2.classyfy.data.RecordField.java
au.com.cybersearch2.classyfy.data.RecordFolder.java
au.com.cybersearch2.classyfy.data.SqlFromNodeGenerator.java
au.com.cybersearch2.classyfy.data.alfresco.AlfrescoFilePlanLoaderModule.java
au.com.cybersearch2.classyfy.data.alfresco.AlfrescoFilePlanLoader.java
au.com.cybersearch2.classyfy.data.alfresco.AlfrescoFilePlanXmlParser.java
au.com.cybersearch2.classyfy.helper.FileUtils.java
au.com.cybersearch2.classyfy.provider.ClassyFyProviderTest.java
au.com.cybersearch2.classyfy.provider.ClassyFyProvider.java
au.com.cybersearch2.classyfy.provider.ClassyFySearchEngine.java
au.com.cybersearch2.classyjpa.entity.LoaderPersistenceContainerTest.java
au.com.cybersearch2.classyjpa.entity.TestPersistenceWork.java
au.com.cybersearch2.classyjpa.entity.UserPersistenceContainerTest.java
au.com.cybersearch2.classyutil.Transcript.java
au.com.cybersearch2.example.AndroidHelloTwoDbsModule.java
au.com.cybersearch2.example.AndroidHelloTwoDbs.java
au.com.cybersearch2.example.AppThreadHelper.java
au.com.cybersearch2.example.AppThreadHelper.java
au.com.cybersearch2.example.HelloTwoDbsEnvironmentModule.java
au.com.cybersearch2.example.HelloTwoDbsEnvironmentModule.java
au.com.cybersearch2.example.v2.AndroidHelloTwoDbsModule.java
au.com.cybersearch2.example.v2.AndroidHelloTwoDbs.java
au.com.cybersearch2.example.v2.HelloTwoDbsEnvironmentModule.java
com.example.hellotwodbs.HelloTwoDbsApplication.java
com.example.hellotwodbs.HelloTwoDbsApplication.java
com.example.hellotwodbs.HelloTwoDbs.java
com.example.hellotwodbs.HelloTwoDbs.java