这一节讲如何实现查询条件。
我们把查询条件封装成了一个类,SdkQueryCondition,它的本质是对ICondition这个COM接口进行的封装。
下面列出SdkQueryCondition类的公共接口。
HRESULT GetCondition(ICondition **ppc); HRESULT SetCondition(LPCWSTR *ppszQuerys, UINT32 uCount); HRESULT SetCondition(INT32 queryKind); HRESULT ClearCondtions();第一个函数GetCondition就是得到ICondition的接口,这个方法是在SdkFileSearcher这个类里面调用的(请参考第一部分)。
#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; }