Windows文件檢索之——查詢條件

這一節講如何實現查詢條件。

我們把查詢條件封裝成了一個類,SdkQueryCondition,它的本質是對ICondition這個COM接口進行的封裝。

1.SdkQueryCondition接口

下面列出SdkQueryCondition類的公共接口。

HRESULT GetCondition(ICondition **ppc);
HRESULT SetCondition(LPCWSTR *ppszQuerys, UINT32 uCount);
HRESULT SetCondition(INT32 queryKind);
HRESULT ClearCondtions();
第一個函數GetCondition就是得到ICondition的接口,這個方法是在SdkFileSearcher這個類裏面調用的(請參考第一部分)。
第二個函數就是設置一個Condition,這個條件可能是後綴數組,如*.txt, *.jpg等。
第三個函數是一個重載,也是用於設置Condition,用戶可以設置一個系統定義的文件類型,如music,video,picture等。
第四個函數就是用來清除上一次設置的查詢條件。

2.SdkQueryCondition實現

SdkQueryCondition.h文件 

#ifdef __cplusplus
#ifndef _QUERYCONDITION_H_
#define _QUERYCONDITION_H_

#include "SdkCommon.h"

/*!
* @brief The search condition kind
*/
typedef enum _QUERYCONDITIONKIND
{
    QUERY_KIND_NONE         = 0x00000000,
    QUERY_KIND_MUSIC        = 0x00000001,
    QUERY_KIND_VIDEO        = 0x00000002,
    QUERY_KIND_PICTURE      = 0x00000004,
    QUERY_KIND_DOCUMENT     = 0x00000008,
    QUERY_KIND_LINK         = 0x00000010,
    QUERY_KIND_RECENT       = 0x00000020,

} QUERYCONDITIONKIND;

/*!
* @brief QueryCondition class to manage searching condition.
*/
class CLASS_DECLSPEC SdkQueryCondition
{
public:

    SdkQueryCondition();
    ~SdkQueryCondition();

    HRESULT GetCondition(ICondition **ppc);
    HRESULT SetCondition(LPCWSTR *ppszQuerys, UINT32 uCount);
    HRESULT SetCondition(INT32 queryKind);
    HRESULT ClearCondtions();

private:

    HRESULT CreateQueryParser();
    HRESULT ParseStructuredQuery(QUERYCONDITIONKIND kind, 
        OUT ICondition **ppc);
    HRESULT ParseStructuredQuery(PCWSTR pszString, 
        OUT ICondition **ppc);
    HRESULT GetQueryKindList(OUT vector<QUERYCONDITIONKIND> &vctKinds);

private:

    // The query kind value.
    INT32                m_nQueryKind;   
    // The count of query condition array.       
    UINT32               m_uQueryCount;   
    // The query condition array.      
    PCWSTR              *m_pszQuerys;   
    // The query parser.        
    IQueryParser        *m_pQueryParser;        
};

#endif // _QUERYCONDITION_H_
#endif // __cplusplus

SdkQueryCondition.cpp文件

#include "SdkQueryCondition.h"

typedef struct _QUERYPARSEROPTIONS
{
    PCWSTR pszPropertyName;
    PCWSTR pszSemanticType;

} QUERYPARSEROPTIONS, *LPQUERYPARSEROPTIONS;

const QUERYPARSEROPTIONS g_rgGenericProperties[] =
{
    { L"System.Generic.String",          L"System.StructuredQueryType.String" },
    { L"System.Generic.Integer",         L"System.StructuredQueryType.Integer" },
    { L"System.Generic.DateTime",        L"System.StructuredQueryType.DateTime" },
    { L"System.Generic.Boolean",         L"System.StructuredQueryType.Boolean" },
    { L"System.Generic.FloatingPoint",   L"System.StructuredQueryType.FloatingPoint" }
};

//////////////////////////////////////////////////////////////////////////

SdkQueryCondition::SdkQueryCondition() : m_pQueryParser(NULL),
                                   m_pszQuerys(NULL),
                                   m_nQueryKind(0),
                                   m_uQueryCount(0)
{
}

//////////////////////////////////////////////////////////////////////////

SdkQueryCondition::~SdkQueryCondition()
{
    SAFE_RELEASE(m_pQueryParser);
    ClearCondtions();
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::GetCondition(ICondition **ppc)
{
    if (NULL == ppc)
    {
        return E_INVALIDARG;
    }

    *ppc = NULL;
    IConditionFactory2 *pConditionFactory = NULL;
    HRESULT hr = CoCreateInstance(CLSID_ConditionFactory, NULL, 
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConditionFactory));
    if (FAILED(hr))
    {
        return hr;
    }

    vector<ICondition*> vctConditions;
    vector<QUERYCONDITIONKIND> vctKinds;
    hr = CreateQueryParser();
    hr = GetQueryKindList(vctKinds);

    for (UINT32 i = 0; i < m_uQueryCount; ++i)
    {
        ICondition *pCondition = NULL;
        hr = ParseStructuredQuery(m_pszQuerys[i], &pCondition);
        if (SUCCEEDED(hr))
        {
            vctConditions.push_back(pCondition);
        }
    }

    for each (QUERYCONDITIONKIND kind in vctKinds)
    {
        ICondition *pCondition = NULL;
        hr = ParseStructuredQuery(kind, &pCondition);
        if (SUCCEEDED(hr))
        {
            vctConditions.push_back(pCondition);
        }
    }

    int conditionCount = vctConditions.size();
    hr = (conditionCount > 0) ? S_OK : E_FAIL;

    if (conditionCount > 0)
    {
        ICondition **pszConditions = new ICondition*[conditionCount];
        for (int i = 0; i < conditionCount; ++i)
        {
            pszConditions[i] = vctConditions[i];
        }

        hr = pConditionFactory->CreateCompoundFromArray(CT_OR_CONDITION,
            pszConditions, conditionCount,
            CONDITION_CREATION_DEFAULT, IID_PPV_ARGS(ppc));

        // Release the memory.
        for (int i = 0; i < conditionCount; ++i)
        {
            SAFE_RELEASE(pszConditions[i]);
        }

        SAFE_DELETE_ARRAY(pszConditions);
    }

    SAFE_RELEASE(pConditionFactory);

    return hr;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::SetCondition(LPCWSTR *ppszQuerys, UINT32 uCount)
{
    if ( (NULL == ppszQuerys) || (0 == uCount) )
    {
        return E_INVALIDARG;
    }

    ClearCondtions();
    m_uQueryCount = uCount;
    m_pszQuerys = new PCWSTR[uCount];
    memset(m_pszQuerys, 0, uCount * sizeof(PCWSTR));

    for (UINT32 i = 0; i < uCount; ++i)
    {
        int length  = wcslen(ppszQuerys[i]);
        int ccbDest = sizeof(WCHAR) * (length + 1);
        int ccbSrc  = sizeof(WCHAR) * length;

        WCHAR *pDest = new WCHAR[length + 1];
        memset(pDest, 0, ccbDest);
        memcpy_s(pDest, ccbDest, ppszQuerys[i], ccbSrc);
        m_pszQuerys[i] = pDest;
    }

    return S_OK;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::SetCondition(INT32 queryKind)
{
    m_nQueryKind = queryKind;

    return S_OK;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::ClearCondtions()
{
    if (NULL != m_pszQuerys)
    {
        for (UINT32 i = 0; i < m_uQueryCount; ++i)
        {
            SAFE_DELETE_ARRAY(m_pszQuerys[i]);
        }

        SAFE_DELETE_ARRAY(m_pszQuerys);
    }

    m_uQueryCount = 0;

    return S_OK;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::CreateQueryParser()
{
    SAFE_RELEASE(m_pQueryParser);
    IQueryParserManager *pQueryParserManager = NULL;

    HRESULT hr = CoCreateInstance(CLSID_QueryParserManager, NULL, 
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pQueryParserManager));
    if (SUCCEEDED(hr))
    {
        IQueryParser *pQueryParser = NULL;
        hr = pQueryParserManager->CreateLoadedParser(L"SystemIndex", 
            LOCALE_USER_DEFAULT, IID_PPV_ARGS(&pQueryParser));
        if (SUCCEEDED(hr))
        {
            hr = pQueryParserManager->InitializeOptions(FALSE, TRUE, pQueryParser);
            for (int i = 0; i < ARRAYSIZE(g_rgGenericProperties) && SUCCEEDED(hr); ++i)
            {
                PCWSTR pszPropertyName = g_rgGenericProperties[i].pszPropertyName;
                PCWSTR pszSemanticType = g_rgGenericProperties[i].pszSemanticType;

                PROPVARIANT propVar;
                hr = InitPropVariantFromString(pszPropertyName, &propVar);
                hr = pQueryParser->SetMultiOption(SQMO_DEFAULT_PROPERTY, 
                    pszSemanticType, &propVar);
                PropVariantClear(&propVar);
            }

            if (SUCCEEDED(hr))
            {
                pQueryParser->QueryInterface(IID_PPV_ARGS(&m_pQueryParser));
            }
        }

        SAFE_RELEASE(pQueryParser);
    }

    SAFE_RELEASE(pQueryParserManager);

    return hr;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::ParseStructuredQuery(QUERYCONDITIONKIND kind, 
    OUT ICondition **ppc)
{
    LPCWSTR strKind = NULL;

    switch (kind)
    {
    case QUERY_KIND_MUSIC:
        strKind = KIND_MUSIC;
        break;

    case QUERY_KIND_VIDEO:
        strKind = KIND_VIDEO;
        break;

    case QUERY_KIND_PICTURE:
        strKind = KIND_PICTURE;
        break;

    case QUERY_KIND_DOCUMENT:
        strKind = KIND_DOCUMENT;
        break;

    case QUERY_KIND_LINK:
        strKind = KIND_LINK;
        break;
    }

    if (NULL == strKind)
    {
        return E_INVALIDARG;
    }

    IConditionFactory2 *pConditionFactory = NULL;
    HRESULT hr = CoCreateInstance(CLSID_ConditionFactory, NULL, 
        CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pConditionFactory));
    if (SUCCEEDED(hr))
    {
        hr = pConditionFactory->CreateStringLeaf(PKEY_Kind, 
            COP_EQUAL, strKind, 
            NULL, CONDITION_CREATION_DEFAULT, IID_PPV_ARGS(ppc));
    }

    SAFE_RELEASE(pConditionFactory);

    return hr;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::ParseStructuredQuery(PCWSTR pszString, 
    OUT ICondition **ppc)
{
    if ( (NULL == ppc) || (NULL == m_pQueryParser) )
    {
        return E_INVALIDARG;
    }

    IQuerySolution *pQuerySolution = NULL;
    HRESULT hr = m_pQueryParser->Parse(pszString, NULL, &pQuerySolution);
    if (SUCCEEDED(hr))
    {
        ICondition *pCondition = NULL;
        hr = pQuerySolution->GetQuery(&pCondition, NULL);
        if (SUCCEEDED(hr))
        {
            SYSTEMTIME sysTime;
            GetLocalTime(&sysTime);
            hr = pQuerySolution->Resolve(pCondition, 
                SQRO_DONT_SPLIT_WORDS, &sysTime, ppc);
        }
        SAFE_RELEASE(pCondition);
    }

    SAFE_RELEASE(pQuerySolution);

    return hr;
}

//////////////////////////////////////////////////////////////////////////

HRESULT SdkQueryCondition::GetQueryKindList(OUT vector<QUERYCONDITIONKIND> &vctKinds)
{
    FILTER_BITVALUE(m_nQueryKind, QUERY_KIND_MUSIC,     vctKinds);
    FILTER_BITVALUE(m_nQueryKind, QUERY_KIND_VIDEO,     vctKinds);
    FILTER_BITVALUE(m_nQueryKind, QUERY_KIND_PICTURE,   vctKinds);
    FILTER_BITVALUE(m_nQueryKind, QUERY_KIND_DOCUMENT,  vctKinds);
    FILTER_BITVALUE(m_nQueryKind, QUERY_KIND_LINK,      vctKinds);

    return S_OK;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章