這一節講如何實現查詢條件。
我們把查詢條件封裝成了一個類,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;
}