зеркало из https://github.com/mozilla/gecko-dev.git
Bug 321171 - support XML sources in XUL templates, r=smaug,sr=peterv CVS: ----------------------------------------------------------------------
This commit is contained in:
Родитель
387d40f5b7
Коммит
439d43e8b3
|
@ -103,6 +103,7 @@ GK_ATOM(applyTemplates, "apply-templates")
|
|||
GK_ATOM(archive, "archive")
|
||||
GK_ATOM(area, "area")
|
||||
GK_ATOM(ascending, "ascending")
|
||||
GK_ATOM(assign, "assign")
|
||||
GK_ATOM(attribute, "attribute")
|
||||
GK_ATOM(attributeSet, "attribute-set")
|
||||
GK_ATOM(aural, "aural")
|
||||
|
@ -320,6 +321,7 @@ GK_ATOM(event, "event")
|
|||
GK_ATOM(events, "events")
|
||||
GK_ATOM(excludeResultPrefixes, "exclude-result-prefixes")
|
||||
GK_ATOM(excludes, "excludes")
|
||||
GK_ATOM(expr, "expr")
|
||||
GK_ATOM(extends, "extends")
|
||||
GK_ATOM(extensionElementPrefixes, "extension-element-prefixes")
|
||||
GK_ATOM(face, "face")
|
||||
|
|
|
@ -87,6 +87,9 @@ CPPSRCS = \
|
|||
nsXULTemplateQueryProcessorRDF.cpp \
|
||||
nsXULTemplateResultRDF.cpp \
|
||||
nsXULTemplateResultSetRDF.cpp \
|
||||
nsXMLBinding.cpp \
|
||||
nsXULTemplateQueryProcessorXML.cpp \
|
||||
nsXULTemplateResultXML.cpp \
|
||||
$(NULL)
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
|
|
|
@ -68,10 +68,8 @@ nsTemplateMatch::RuleMatched(nsTemplateQuerySet* aQuerySet,
|
|||
|
||||
nsCOMPtr<nsIDOMNode> rulenode;
|
||||
aRule->GetRuleNode(getter_AddRefs(rulenode));
|
||||
if (rulenode) {
|
||||
nsCOMPtr<nsIDOMNode> querynode = do_QueryInterface(aQuerySet->mQueryNode);
|
||||
return aResult->RuleMatched(querynode, rulenode);
|
||||
}
|
||||
if (rulenode)
|
||||
return aResult->RuleMatched(aQuerySet->mCompiledQuery, rulenode);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
#include "nsXMLBinding.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsXMLBindingSet);
|
||||
NS_IMPL_RELEASE(nsXMLBindingSet);
|
||||
|
||||
nsresult
|
||||
nsXMLBindingSet::AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
|
||||
{
|
||||
nsAutoPtr<nsXMLBinding> newbinding(new nsXMLBinding(aVar, aExpr));
|
||||
NS_ENSURE_TRUE(newbinding, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (mFirst) {
|
||||
nsXMLBinding* binding = mFirst;
|
||||
|
||||
while (binding) {
|
||||
// if the target variable is already used in a binding, ignore it
|
||||
// since it won't be useful for anything
|
||||
if (binding->mVar == aVar)
|
||||
return NS_OK;
|
||||
|
||||
// add the binding at the end of the list
|
||||
if (!binding->mNext) {
|
||||
binding->mNext = newbinding;
|
||||
break;
|
||||
}
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mFirst = newbinding;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXMLBindingSet::LookupTargetIndex(nsIAtom* aTargetVariable,
|
||||
nsXMLBinding** aBinding)
|
||||
{
|
||||
PRInt32 idx = 0;
|
||||
nsXMLBinding* binding = mFirst;
|
||||
|
||||
while (binding) {
|
||||
if (binding->mVar == aTargetVariable) {
|
||||
*aBinding = binding;
|
||||
return idx;
|
||||
}
|
||||
idx++;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
*aBinding = nsnull;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLBindingValues::GetAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 aIndex,
|
||||
PRUint16 aType,
|
||||
nsIDOMXPathResult** aValue)
|
||||
{
|
||||
*aValue = mValues.SafeObjectAt(aIndex);
|
||||
|
||||
if (!*aValue) {
|
||||
nsCOMPtr<nsIDOMNode> contextNode;
|
||||
aResult->GetNode(getter_AddRefs(contextNode));
|
||||
if (contextNode) {
|
||||
nsCOMPtr<nsISupports> resultsupports;
|
||||
aBinding->mExpr->Evaluate(contextNode, aType,
|
||||
nsnull, getter_AddRefs(resultsupports));
|
||||
|
||||
nsCOMPtr<nsIDOMXPathResult> result = do_QueryInterface(resultsupports);
|
||||
if (result && mValues.ReplaceObjectAt(result, aIndex))
|
||||
*aValue = result;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*aValue);
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLBindingValues::GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 aIndex,
|
||||
nsIDOMNode** aNode)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathResult> result;
|
||||
GetAssignmentFor(aResult, aBinding, aIndex,
|
||||
nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
|
||||
getter_AddRefs(result));
|
||||
|
||||
if (result)
|
||||
result->GetSingleNodeValue(aNode);
|
||||
else
|
||||
*aNode = nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLBindingValues::GetStringAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 aIndex,
|
||||
nsAString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathResult> result;
|
||||
GetAssignmentFor(aResult, aBinding, aIndex,
|
||||
nsIDOMXPathResult::STRING_TYPE, getter_AddRefs(result));
|
||||
|
||||
if (result)
|
||||
result->GetStringValue(aValue);
|
||||
else
|
||||
aValue.Truncate();
|
||||
}
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXMLBinding_h__
|
||||
#define nsXMLBinding_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIAtom.h"
|
||||
|
||||
class nsXULTemplateResultXML;
|
||||
class nsXMLBindingValues;
|
||||
|
||||
/**
|
||||
* Classes related to storing bindings for XML handling.
|
||||
*/
|
||||
|
||||
/**
|
||||
* a <binding> description
|
||||
*/
|
||||
struct nsXMLBinding {
|
||||
nsCOMPtr<nsIAtom> mVar;
|
||||
nsCOMPtr<nsIDOMXPathExpression> mExpr;
|
||||
|
||||
nsAutoPtr<nsXMLBinding> mNext;
|
||||
|
||||
nsXMLBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
|
||||
: mVar(aVar), mExpr(aExpr), mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXMLBinding);
|
||||
}
|
||||
|
||||
~nsXMLBinding()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXMLBinding);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* a collection of <binding> descriptors. This object is refcounted by
|
||||
* nsXMLBindingValues objects and the query processor.
|
||||
*/
|
||||
class nsXMLBindingSet
|
||||
{
|
||||
public:
|
||||
|
||||
// results hold a reference to a binding set in their
|
||||
// nsXMLBindingValues fields
|
||||
nsAutoRefCnt mRefCnt;
|
||||
|
||||
// pointer to the first binding in a linked list
|
||||
nsAutoPtr<nsXMLBinding> mFirst;
|
||||
|
||||
public:
|
||||
|
||||
nsrefcnt AddRef();
|
||||
nsrefcnt Release();
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
/**
|
||||
* Add a binding to the set
|
||||
*/
|
||||
nsresult
|
||||
AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr);
|
||||
|
||||
/**
|
||||
* The nsXMLBindingValues class stores an array of values, one for each
|
||||
* target symbol that could be set by the bindings in the set.
|
||||
* LookupTargetIndex determines the index into the array for a given
|
||||
* target symbol.
|
||||
*/
|
||||
PRInt32
|
||||
LookupTargetIndex(nsIAtom* aTargetVariable, nsXMLBinding** aBinding);
|
||||
};
|
||||
|
||||
/**
|
||||
* a set of values of bindings. This object is used once per result.
|
||||
*/
|
||||
class nsXMLBindingValues
|
||||
{
|
||||
protected:
|
||||
|
||||
// the binding set
|
||||
nsRefPtr<nsXMLBindingSet> mBindings;
|
||||
|
||||
/**
|
||||
* A set of values for variable bindings. To look up a binding value,
|
||||
* scan through the binding set in mBindings for the right target atom.
|
||||
* Its index will correspond to the index in this array.
|
||||
*/
|
||||
nsCOMArray<nsIDOMXPathResult> mValues;
|
||||
|
||||
public:
|
||||
|
||||
nsXMLBindingValues() { MOZ_COUNT_CTOR(nsXMLBindingValues); }
|
||||
~nsXMLBindingValues() { MOZ_COUNT_DTOR(nsXMLBindingValues); }
|
||||
|
||||
nsXMLBindingSet* GetBindingSet() { return mBindings; }
|
||||
|
||||
void SetBindingSet(nsXMLBindingSet* aBindings) { mBindings = aBindings; }
|
||||
|
||||
PRInt32
|
||||
LookupTargetIndex(nsIAtom* aTargetVariable, nsXMLBinding** aBinding)
|
||||
{
|
||||
return mBindings ?
|
||||
mBindings->LookupTargetIndex(aTargetVariable, aBinding) : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the assignment for a particular variable
|
||||
*
|
||||
* aResult the result generated from the template
|
||||
* aBinding the binding looked up using LookupTargetIndex
|
||||
* aIndex the index of the assignment to retrieve
|
||||
* aType the type of result expected
|
||||
* aValue the value of the assignment
|
||||
*/
|
||||
void
|
||||
GetAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 idx,
|
||||
PRUint16 type,
|
||||
nsIDOMXPathResult** aValue);
|
||||
|
||||
void
|
||||
GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 idx,
|
||||
nsIDOMNode** aValue);
|
||||
|
||||
void
|
||||
GetStringAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
PRInt32 idx,
|
||||
nsAString& aValue);
|
||||
};
|
||||
|
||||
#endif // nsXMLBinding_h__
|
|
@ -944,9 +944,12 @@ nsXULContentBuilder::AddPersistentAttributes(nsIContent* aTemplateNode,
|
|||
nsIXULTemplateResult* aResult,
|
||||
nsIContent* aRealNode)
|
||||
{
|
||||
if (!mRoot)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
nsresult rv = GetResultResource(aResult, getter_AddRefs(resource));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString attribute, persist;
|
||||
aTemplateNode->GetAttr(kNameSpaceID_None, nsGkAtoms::persist, persist);
|
||||
|
@ -987,11 +990,11 @@ nsXULContentBuilder::AddPersistentAttributes(nsIContent* aTemplateNode,
|
|||
|
||||
nsCOMPtr<nsIRDFResource> property;
|
||||
rv = nsXULContentUtils::GetResource(nameSpaceID, tag, getter_AddRefs(property));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRDFNode> target;
|
||||
rv = mDB->GetTarget(resource, property, PR_TRUE, getter_AddRefs(target));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (! target)
|
||||
continue;
|
||||
|
@ -1003,11 +1006,11 @@ nsXULContentBuilder::AddPersistentAttributes(nsIContent* aTemplateNode,
|
|||
|
||||
const PRUnichar* valueStr;
|
||||
rv = value->GetValueConst(&valueStr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = aRealNode->SetAttr(nameSpaceID, tag, nsDependentString(valueStr),
|
||||
PR_FALSE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1137,7 +1140,7 @@ nsXULContentBuilder::CreateTemplateAndContainerContents(nsIContent* aElement,
|
|||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, ref);
|
||||
|
||||
if (! ref.IsEmpty()) {
|
||||
nsresult rv = mQueryProcessor->TranslateRef(mDB, ref,
|
||||
nsresult rv = mQueryProcessor->TranslateRef(mDataSource, ref,
|
||||
getter_AddRefs(mRootResult));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
@ -1278,7 +1281,7 @@ nsXULContentBuilder::CreateContainerContentsForQuerySet(nsIContent* aElement,
|
|||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> results;
|
||||
nsresult rv = mQueryProcessor->GenerateResults(mDB, aResult,
|
||||
nsresult rv = mQueryProcessor->GenerateResults(mDataSource, aResult,
|
||||
aQuerySet->mCompiledQuery,
|
||||
getter_AddRefs(results));
|
||||
if (NS_FAILED(rv) || !results)
|
||||
|
|
|
@ -62,6 +62,8 @@
|
|||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIPrivateDOMImplementation.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsBindingManager.h"
|
||||
|
@ -99,6 +101,7 @@
|
|||
#include "nsNetUtil.h"
|
||||
#include "nsXULTemplateBuilder.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
|
@ -128,10 +131,7 @@ PRLogModuleInfo* gXULTemplateLog;
|
|||
//
|
||||
|
||||
nsXULTemplateBuilder::nsXULTemplateBuilder(void)
|
||||
: mDB(nsnull),
|
||||
mCompDB(nsnull),
|
||||
mRoot(nsnull),
|
||||
mQueriesCompiled(PR_FALSE),
|
||||
: mQueriesCompiled(PR_FALSE),
|
||||
mFlags(0),
|
||||
mTop(nsnull)
|
||||
{
|
||||
|
@ -246,10 +246,12 @@ TraverseMatchList(nsISupports* aKey, nsTemplateMatch* aMatch, void* aContext)
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDataSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mCompDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDataSource)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCompDB)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mRoot)
|
||||
|
@ -300,7 +302,7 @@ nsXULTemplateBuilder::GetRoot(nsIDOMElement** aResult)
|
|||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::GetDatabase(nsIRDFCompositeDataSource** aResult)
|
||||
{
|
||||
NS_IF_ADDREF(*aResult = mCompDB.get());
|
||||
NS_IF_ADDREF(*aResult = mCompDB);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -364,6 +366,9 @@ nsXULTemplateBuilder::Refresh()
|
|||
{
|
||||
nsresult rv;
|
||||
|
||||
if (!mCompDB)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> dslist;
|
||||
rv = mCompDB->GetDataSources(getter_AddRefs(dslist));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -396,36 +401,14 @@ nsXULTemplateBuilder::Init(nsIContent* aElement)
|
|||
if (! doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsresult rv = LoadDataSources(doc);
|
||||
PRBool shouldDelay;
|
||||
nsresult rv = LoadDataSources(doc, &shouldDelay);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Add ourselves as a document observer
|
||||
doc->AddObserver(this);
|
||||
}
|
||||
|
||||
// create the query processor. The querytype attribute on the root element
|
||||
// may be used to create one of a specific type.
|
||||
|
||||
// XXX should non-chrome be restricted to specific names?
|
||||
|
||||
nsAutoString type;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::querytype, type);
|
||||
|
||||
if (type.IsEmpty() || type.EqualsLiteral("rdf")) {
|
||||
mQueryProcessor = new nsXULTemplateQueryProcessorRDF();
|
||||
if (! mQueryProcessor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
else {
|
||||
nsCAutoString cid(NS_QUERY_PROCESSOR_CONTRACTID_PREFIX);
|
||||
AppendUTF16toUTF8(type, cid);
|
||||
mQueryProcessor = do_CreateInstance(cid.get(), &rv);
|
||||
if (!mQueryProcessor) {
|
||||
// XXXndeakin should log an error here
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -1066,8 +1049,10 @@ nsXULTemplateBuilder::AttributeChanged(nsIDocument* aDocument,
|
|||
// Check for a change to the 'datasources' attribute. If so, setup
|
||||
// mDB by parsing the vew value and rebuild.
|
||||
else if (aAttribute == nsGkAtoms::datasources) {
|
||||
LoadDataSources(aDocument);
|
||||
Rebuild();
|
||||
PRBool shouldDelay;
|
||||
LoadDataSources(aDocument, &shouldDelay);
|
||||
if (!shouldDelay)
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1118,6 +1103,7 @@ nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
|||
if (mQueryProcessor)
|
||||
mQueryProcessor->Done();
|
||||
|
||||
mDataSource = nsnull;
|
||||
mDB = nsnull;
|
||||
mCompDB = nsnull;
|
||||
mRoot = nsnull;
|
||||
|
@ -1134,57 +1120,144 @@ nsXULTemplateBuilder::NodeWillBeDestroyed(const nsINode* aNode)
|
|||
//
|
||||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::LoadDataSources(nsIDocument* doc)
|
||||
nsXULTemplateBuilder::LoadDataSources(nsIDocument* aDocument,
|
||||
PRBool* aShouldDelayBuilding)
|
||||
{
|
||||
NS_PRECONDITION(mRoot != nsnull, "not initialized");
|
||||
|
||||
nsresult rv;
|
||||
PRBool isRDFQuery = PR_FALSE;
|
||||
|
||||
// we'll set these again later, after we create a new composite ds
|
||||
mDB = nsnull;
|
||||
mCompDB = nsnull;
|
||||
mDataSource = nsnull;
|
||||
|
||||
if (mDB) {
|
||||
// we'll set it again later, after we create a new composite ds
|
||||
mDB = nsnull;
|
||||
*aShouldDelayBuilding = PR_TRUE;
|
||||
|
||||
nsAutoString datasources;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::datasources, datasources);
|
||||
|
||||
nsAutoString querytype;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::querytype, querytype);
|
||||
|
||||
// if the datasources begins with '#', it is a reference to a node
|
||||
// within the same document.
|
||||
PRBool shouldLoadUrls = PR_TRUE;
|
||||
if (datasources.CharAt(0) == '#') {
|
||||
shouldLoadUrls = PR_FALSE;
|
||||
|
||||
if (querytype.IsEmpty()) {
|
||||
querytype.AssignLiteral("xml");
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(aDocument);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> dsnode;
|
||||
domdoc->GetElementById(Substring(datasources, 1),
|
||||
getter_AddRefs(dsnode));
|
||||
if (dsnode) {
|
||||
mDataSource = dsnode;
|
||||
*aShouldDelayBuilding = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// create the query processor. The querytype attribute on the root element
|
||||
// may be used to create one of a specific type.
|
||||
|
||||
// XXX should non-chrome be restricted to specific names?
|
||||
if (querytype.IsEmpty())
|
||||
querytype.AssignLiteral("rdf");
|
||||
|
||||
if (querytype.EqualsLiteral("rdf")) {
|
||||
isRDFQuery = PR_TRUE;
|
||||
mQueryProcessor = new nsXULTemplateQueryProcessorRDF();
|
||||
NS_ENSURE_TRUE(mQueryProcessor, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else if (querytype.EqualsLiteral("xml")) {
|
||||
mQueryProcessor = new nsXULTemplateQueryProcessorXML();
|
||||
NS_ENSURE_TRUE(mQueryProcessor, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
else {
|
||||
shouldLoadUrls = PR_FALSE;
|
||||
|
||||
nsCAutoString cid(NS_QUERY_PROCESSOR_CONTRACTID_PREFIX);
|
||||
AppendUTF16toUTF8(querytype, cid);
|
||||
mQueryProcessor = do_CreateInstance(cid.get(), &rv);
|
||||
// XXXndeakin log an error here - bug 321169
|
||||
NS_ENSURE_TRUE(mQueryProcessor, rv);
|
||||
}
|
||||
|
||||
// create a database for the builder
|
||||
mCompDB = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "composite-datasource");
|
||||
|
||||
if (! mCompDB) {
|
||||
NS_ERROR("unable to construct new composite data source");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
if (shouldLoadUrls) {
|
||||
rv = LoadDataSourceUrls(aDocument, datasources,
|
||||
isRDFQuery, aShouldDelayBuilding);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// check for magical attributes. XXX move to ``flags''?
|
||||
if (mRoot->AttrValueIs(kNameSpaceID_None, nsGkAtoms::coalesceduplicatearcs,
|
||||
nsGkAtoms::_false, eCaseMatters))
|
||||
mCompDB->SetCoalesceDuplicateArcs(PR_FALSE);
|
||||
|
||||
if (mRoot->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allownegativeassertions,
|
||||
nsGkAtoms::_false, eCaseMatters))
|
||||
mCompDB->SetAllowNegativeAssertions(PR_FALSE);
|
||||
// Now set the database on the element, so that script writers can
|
||||
// access it.
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(aDocument);
|
||||
if (xuldoc)
|
||||
xuldoc->SetTemplateBuilderFor(mRoot, this);
|
||||
|
||||
if (!mRoot->IsNodeOfType(nsINode::eXUL)) {
|
||||
// Hmm. This must be an HTML element. Try to set it as a
|
||||
// JS property "by hand".
|
||||
InitHTMLTemplateRoot();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::LoadDataSourceUrls(nsIDocument* aDocument,
|
||||
const nsAString& aDataSources,
|
||||
PRBool aIsRDFQuery,
|
||||
PRBool* aShouldDelayBuilding)
|
||||
{
|
||||
// Grab the doc's principal...
|
||||
nsIPrincipal *docPrincipal = doc->NodePrincipal();
|
||||
nsIPrincipal *docPrincipal = aDocument->NodePrincipal();
|
||||
|
||||
NS_ASSERTION(docPrincipal == mRoot->NodePrincipal(),
|
||||
"Principal mismatch? Which one to use?");
|
||||
|
||||
PRBool isTrusted = PR_FALSE;
|
||||
rv = IsSystemPrincipal(docPrincipal, &isTrusted);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
nsresult rv = IsSystemPrincipal(docPrincipal, &isTrusted);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIRDFDataSource> localstore;
|
||||
if (isTrusted) {
|
||||
// If we're a privileged (e.g., chrome) document, then add the
|
||||
// local store as the first data source in the db. Note that
|
||||
// we _might_ not be able to get a local store if we haven't
|
||||
// got a profile to read from yet.
|
||||
nsCOMPtr<nsIRDFDataSource> localstore;
|
||||
rv = gRDFService->GetDataSource("rdf:local-store", getter_AddRefs(localstore));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
if (aIsRDFQuery) {
|
||||
// create a database for the builder
|
||||
mCompDB = do_CreateInstance(NS_RDF_DATASOURCE_CONTRACTID_PREFIX "composite-datasource");
|
||||
if (! mCompDB) {
|
||||
NS_ERROR("unable to construct new composite data source");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// check for magical attributes. XXX move to ``flags''?
|
||||
if (mRoot->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::coalesceduplicatearcs,
|
||||
nsGkAtoms::_false, eCaseMatters))
|
||||
mCompDB->SetCoalesceDuplicateArcs(PR_FALSE);
|
||||
|
||||
if (mRoot->AttrValueIs(kNameSpaceID_None,
|
||||
nsGkAtoms::allownegativeassertions,
|
||||
nsGkAtoms::_false, eCaseMatters))
|
||||
mCompDB->SetAllowNegativeAssertions(PR_FALSE);
|
||||
|
||||
if (localstore) {
|
||||
// If we're a privileged (e.g., chrome) document, then add the
|
||||
// local store as the first data source in the db. Note that
|
||||
// we _might_ not be able to get a local store if we haven't
|
||||
// got a profile to read from yet.
|
||||
rv = mCompDB->AddDataSource(localstore);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to add local store to db");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1193,14 +1266,11 @@ nsXULTemplateBuilder::LoadDataSources(nsIDocument* doc)
|
|||
//
|
||||
// rdf:bookmarks rdf:history http://foo.bar.com/blah.cgi?baz=9
|
||||
//
|
||||
nsIURI *docurl = doc->GetDocumentURI();
|
||||
|
||||
nsAutoString datasources;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::datasources, datasources);
|
||||
|
||||
nsIURI *docurl = aDocument->GetDocumentURI();
|
||||
|
||||
nsAutoString datasources(aDataSources);
|
||||
PRUint32 first = 0;
|
||||
|
||||
while(1) {
|
||||
while (1) {
|
||||
while (first < datasources.Length() && nsCRT::IsAsciiSpace(datasources.CharAt(first)))
|
||||
++first;
|
||||
|
||||
|
@ -1223,6 +1293,7 @@ nsXULTemplateBuilder::LoadDataSources(nsIDocument* doc)
|
|||
// protocol) leaves uriStr unaltered.
|
||||
NS_MakeAbsoluteURI(uriStr, uriStr, docurl);
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (!isTrusted) {
|
||||
// Our document is untrusted, so check to see if we can
|
||||
// load the datasource that they've asked for.
|
||||
|
@ -1231,17 +1302,14 @@ nsXULTemplateBuilder::LoadDataSources(nsIDocument* doc)
|
|||
if (NS_FAILED(rv) || !uri)
|
||||
continue; // Necko will barf if our URI is weird
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = gScriptSecurityManager->GetCodebasePrincipal(uri, getter_AddRefs(principal));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get codebase principal");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool same;
|
||||
rv = docPrincipal->Equals(principal, &same);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to test same origin");
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (! same)
|
||||
continue;
|
||||
|
@ -1251,64 +1319,90 @@ nsXULTemplateBuilder::LoadDataSources(nsIDocument* doc)
|
|||
// document. Let it load!
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFDataSource> ds;
|
||||
nsCAutoString uristrC;
|
||||
uristrC.AssignWithConversion(uriStr);
|
||||
if (aIsRDFQuery) {
|
||||
nsCOMPtr<nsIRDFDataSource> ds;
|
||||
nsCAutoString uristrC;
|
||||
uristrC.AssignWithConversion(uriStr);
|
||||
|
||||
rv = gRDFService->GetDataSource(uristrC.get(), getter_AddRefs(ds));
|
||||
rv = gRDFService->GetDataSource(uristrC.get(), getter_AddRefs(ds));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
// This is only a warning because the data source may not
|
||||
// be accessible for any number of reasons, including
|
||||
// security, a bad URL, etc.
|
||||
#ifdef DEBUG
|
||||
nsCAutoString msg;
|
||||
msg.Append("unable to load datasource '");
|
||||
msg.AppendWithConversion(uriStr);
|
||||
msg.Append('\'');
|
||||
NS_WARNING(msg.get());
|
||||
#endif
|
||||
continue;
|
||||
if (NS_FAILED(rv)) {
|
||||
// This is only a warning because the data source may not
|
||||
// be accessible for any number of reasons, including
|
||||
// security, a bad URL, etc.
|
||||
#ifdef DEBUG
|
||||
nsCAutoString msg;
|
||||
msg.Append("unable to load datasource '");
|
||||
msg.AppendWithConversion(uriStr);
|
||||
msg.Append('\'');
|
||||
NS_WARNING(msg.get());
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
mCompDB->AddDataSource(ds);
|
||||
}
|
||||
else {
|
||||
nsAutoString emptyStr;
|
||||
nsCOMPtr<nsIDOMDocument> domDocument;
|
||||
rv = nsContentUtils::CreateDocument(emptyStr, emptyStr, nsnull,
|
||||
docurl, aDocument->GetBaseURI(),
|
||||
docPrincipal,
|
||||
getter_AddRefs(domDocument));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mCompDB->AddDataSource(ds);
|
||||
}
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(domDocument);
|
||||
target->AddEventListener(NS_LITERAL_STRING("load"), this, PR_FALSE);
|
||||
|
||||
nsCOMPtr<nsIDOMXMLDocument> xmldoc = do_QueryInterface(domDocument);
|
||||
|
||||
// check if we were given an inference engine type
|
||||
nsAutoString infer;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::infer, infer);
|
||||
if (!infer.IsEmpty()) {
|
||||
nsCString inferContractID(NS_RDF_INFER_DATASOURCE_CONTRACTID_PREFIX);
|
||||
AppendUTF16toUTF8(infer, inferContractID);
|
||||
nsCOMPtr<nsIRDFInferDataSource> inferDB = do_CreateInstance(inferContractID.get());
|
||||
|
||||
if (inferDB) {
|
||||
inferDB->SetBaseDataSource(mCompDB);
|
||||
mDB = do_QueryInterface(inferDB);
|
||||
} else {
|
||||
NS_WARNING("failed to construct inference engine specified on template");
|
||||
PRBool ok;
|
||||
xmldoc->Load(uriStr, &ok);
|
||||
if (ok) {
|
||||
mDataSource = domDocument;
|
||||
*aShouldDelayBuilding = PR_TRUE;
|
||||
}
|
||||
|
||||
// only one XML datasource is supported currently
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (aIsRDFQuery) {
|
||||
// check if we were given an inference engine type
|
||||
nsAutoString infer;
|
||||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::infer, infer);
|
||||
if (!infer.IsEmpty()) {
|
||||
nsCString inferCID(NS_RDF_INFER_DATASOURCE_CONTRACTID_PREFIX);
|
||||
AppendUTF16toUTF8(infer, inferCID);
|
||||
nsCOMPtr<nsIRDFInferDataSource> inferDB =
|
||||
do_CreateInstance(inferCID.get());
|
||||
|
||||
if (!mDB)
|
||||
mDB = mCompDB;
|
||||
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(doc);
|
||||
if (xuldoc)
|
||||
xuldoc->SetTemplateBuilderFor(mRoot, this);
|
||||
|
||||
// Now set the database on the element, so that script writers can
|
||||
// access it.
|
||||
nsXULElement *xulcontent = nsXULElement::FromContent(mRoot);
|
||||
if (! xulcontent) {
|
||||
// Hmm. This must be an HTML element. Try to set it as a
|
||||
// JS property "by hand".
|
||||
InitHTMLTemplateRoot();
|
||||
if (inferDB) {
|
||||
inferDB->SetBaseDataSource(mCompDB);
|
||||
mDB = do_QueryInterface(inferDB);
|
||||
} else {
|
||||
NS_WARNING("failed to construct inference engine specified on template");
|
||||
}
|
||||
}
|
||||
|
||||
if (!mDB)
|
||||
mDB = mCompDB;
|
||||
mDataSource = mDB;
|
||||
}
|
||||
else {
|
||||
mDB = localstore;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateBuilder::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return Rebuild();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTemplateBuilder::InitHTMLTemplateRoot()
|
||||
{
|
||||
|
@ -1348,7 +1442,7 @@ nsXULTemplateBuilder::InitHTMLTemplateRoot()
|
|||
rv = wrapper->GetJSObject(&jselement);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
{
|
||||
if (mDB) {
|
||||
// database
|
||||
rv = xpc->WrapNative(jscontext, scope, mDB,
|
||||
NS_GET_IID(nsIRDFCompositeDataSource),
|
||||
|
@ -1687,7 +1781,8 @@ nsXULTemplateBuilder::CompileQueries()
|
|||
mFlags |= eDontRecurse;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> rootnode = do_QueryInterface(mRoot);
|
||||
nsresult rv = mQueryProcessor->InitializeForBuilding(mDB, this, rootnode);
|
||||
nsresult rv =
|
||||
mQueryProcessor->InitializeForBuilding(mDataSource, this, rootnode);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -1989,14 +2084,15 @@ nsXULTemplateBuilder::CompileExtendedQuery(nsIContent* aRuleElement,
|
|||
nsGkAtoms::conditions,
|
||||
getter_AddRefs(conditions));
|
||||
|
||||
if (conditions) {
|
||||
rv = CompileConditions(rule, conditions);
|
||||
|
||||
// If the rule compilation failed, then we have to bail.
|
||||
if (NS_FAILED(rv)) {
|
||||
delete rule;
|
||||
return rv;
|
||||
}
|
||||
// allow the conditions to be placed directly inside the rule
|
||||
if (!conditions)
|
||||
conditions = aRuleElement;
|
||||
|
||||
rv = CompileConditions(rule, conditions);
|
||||
// If the rule compilation failed, then we have to bail.
|
||||
if (NS_FAILED(rv)) {
|
||||
delete rule;
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = aQuerySet->AddRule(rule);
|
||||
|
@ -2014,11 +2110,12 @@ nsXULTemplateBuilder::CompileExtendedQuery(nsIContent* aRuleElement,
|
|||
nsGkAtoms::bindings,
|
||||
getter_AddRefs(bindings));
|
||||
|
||||
if (bindings) {
|
||||
rv = CompileBindings(rule, bindings);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
// allow bindings to be placed directly inside rule
|
||||
if (!bindings)
|
||||
bindings = aRuleElement;
|
||||
|
||||
rv = CompileBindings(rule, bindings);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
#include "nsFixedSizeAllocator.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
@ -77,6 +78,7 @@ class nsIRDFCompositeDataSource;
|
|||
* set of rules.
|
||||
*/
|
||||
class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
|
||||
public nsIDOMEventListener,
|
||||
public nsStubDocumentObserver
|
||||
{
|
||||
public:
|
||||
|
@ -98,7 +100,9 @@ public:
|
|||
|
||||
// nsIXULTemplateBuilder interface
|
||||
NS_DECL_NSIXULTEMPLATEBUILDER
|
||||
|
||||
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
// nsIDocumentObserver
|
||||
virtual void AttributeChanged(nsIDocument *aDocument, nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
||||
|
@ -274,8 +278,30 @@ public:
|
|||
const nsAString& aVariable,
|
||||
void* aClosure);
|
||||
|
||||
/**
|
||||
* Load the datasources for the template. shouldDelayBuilding is an out
|
||||
* parameter which will be set to true to indicate that content building
|
||||
* should not be performed yet as the datasource has not yet loaded. If
|
||||
* false, the datasource has already loaded so building can proceed
|
||||
* immediately. In the former case, the datasource or query processor
|
||||
* should either rebuild the template or update results when the
|
||||
* datasource is loaded as needed.
|
||||
*/
|
||||
nsresult
|
||||
LoadDataSources(nsIDocument* aDoc);
|
||||
LoadDataSources(nsIDocument* aDoc, PRBool* shouldDelayBuilding);
|
||||
|
||||
/**
|
||||
* Called by LoadDataSources to load a datasource given a uri list
|
||||
* in aDataSource. The list is a set of uris separated by spaces.
|
||||
* If aIsRDFQuery is true, then this is for an RDF datasource which
|
||||
* causes the method to check for additional flags specific to the
|
||||
* RDF processor.
|
||||
*/
|
||||
nsresult
|
||||
LoadDataSourceUrls(nsIDocument* aDocument,
|
||||
const nsAString& aDataSources,
|
||||
PRBool aIsRDFQuery,
|
||||
PRBool* aShouldDelayBuilding);
|
||||
|
||||
nsresult
|
||||
InitHTMLTemplateRoot();
|
||||
|
@ -330,6 +356,7 @@ public:
|
|||
nsIRDFResource** aResource);
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsISupports> mDataSource;
|
||||
nsCOMPtr<nsIRDFDataSource> mDB;
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
|
||||
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#include "nsXULTemplateBuilder.h"
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXMLQuery, nsXMLQuery)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateResultSetXML
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXULTemplateResultSetXML, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetXML::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
// if GetSnapshotLength failed, then the return type was not a set of
|
||||
// nodes, so just return false in this case.
|
||||
PRUint32 length;
|
||||
if (NS_SUCCEEDED(mResults->GetSnapshotLength(&length)))
|
||||
*aResult = (mPosition < length);
|
||||
else
|
||||
*aResult = PR_FALSE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsresult rv = mResults->SnapshotItem(mPosition, getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXULTemplateResultXML* result =
|
||||
new nsXULTemplateResultXML(mQuery, node, mBindingSet);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
++mPosition;
|
||||
*aResult = result;
|
||||
NS_ADDREF(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateQueryProcessorXML
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXULTemplateQueryProcessorXML, nsIXULTemplateQueryProcessor)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::InitializeForBuilding(nsISupports* aDatasource,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aRootNode)
|
||||
{
|
||||
// the datasource is either a document or a DOM element
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
|
||||
if (doc)
|
||||
doc->GetDocumentElement(getter_AddRefs(mRoot));
|
||||
else
|
||||
mRoot = do_QueryInterface(aDatasource);
|
||||
NS_ENSURE_STATE(mRoot);
|
||||
|
||||
mEvaluator = do_CreateInstance("@mozilla.org/dom/xpath-evaluator;1");
|
||||
NS_ENSURE_TRUE(mEvaluator, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
if (!mRuleToBindingsMap.IsInitialized() &&
|
||||
!mRuleToBindingsMap.Init())
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::Done()
|
||||
{
|
||||
mGenerationStarted = PR_FALSE;
|
||||
|
||||
if (mRuleToBindingsMap.IsInitialized())
|
||||
mRuleToBindingsMap.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::CompileQuery(nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aQueryNode,
|
||||
nsIAtom* aRefVariable,
|
||||
nsIAtom* aMemberVariable,
|
||||
nsISupports** _retval)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
*_retval = nsnull;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
|
||||
|
||||
nsAutoString expr;
|
||||
content->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
|
||||
|
||||
// if an expression is not specified, then the default is to
|
||||
// just take all of the children
|
||||
if (expr.IsEmpty())
|
||||
expr.AssignLiteral("*");
|
||||
|
||||
nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
|
||||
rv = CreateExpression(expr, aQueryNode, getter_AddRefs(compiledexpr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsXMLQuery> query =
|
||||
new nsXMLQuery(this, aMemberVariable, compiledexpr);
|
||||
NS_ENSURE_TRUE(query, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
PRUint32 count = content->GetChildCount();
|
||||
for (PRUint32 i = 0; i < count; ++i) {
|
||||
nsIContent *condition = content->GetChildAt(i);
|
||||
if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
|
||||
kNameSpaceID_XUL)) {
|
||||
nsAutoString var;
|
||||
condition->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
|
||||
|
||||
nsAutoString expr;
|
||||
condition->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
|
||||
|
||||
// ignore assignments without a variable or an expression
|
||||
if (!var.IsEmpty() && !expr.IsEmpty()) {
|
||||
nsCOMPtr<nsIDOMNode> conditionNode =
|
||||
do_QueryInterface(condition);
|
||||
rv = CreateExpression(expr, conditionNode,
|
||||
getter_AddRefs(compiledexpr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIAtom> varatom = do_GetAtom(var);
|
||||
|
||||
rv = query->AddBinding(varatom, compiledexpr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*_retval = query;
|
||||
NS_ADDREF(*_retval);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::GenerateResults(nsISupports* aDatasource,
|
||||
nsIXULTemplateResult* aRef,
|
||||
nsISupports* aQuery,
|
||||
nsISimpleEnumerator** aResults)
|
||||
{
|
||||
if (!aQuery)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mGenerationStarted = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsXMLQuery> xmlquery = do_QueryInterface(aQuery);
|
||||
if (!xmlquery)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> context;
|
||||
aRef->GetBindingObjectFor(xmlquery->GetMemberVariable(),
|
||||
getter_AddRefs(context));
|
||||
if (!context)
|
||||
context = mRoot;
|
||||
|
||||
nsIDOMXPathExpression* expr = xmlquery->GetResultsExpression();
|
||||
if (!expr)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsISupports> exprsupportsresults;
|
||||
nsresult rv = expr->Evaluate(context,
|
||||
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
|
||||
nsnull, getter_AddRefs(exprsupportsresults));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMXPathResult> exprresults =
|
||||
do_QueryInterface(exprsupportsresults);
|
||||
|
||||
nsXULTemplateResultSetXML* results =
|
||||
new nsXULTemplateResultSetXML(xmlquery, exprresults,
|
||||
xmlquery->GetBindingSet());
|
||||
NS_ENSURE_TRUE(results, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*aResults = results;
|
||||
NS_ADDREF(*aResults);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::AddBinding(nsIDOMNode* aRuleNode,
|
||||
nsIAtom* aVar,
|
||||
nsIAtom* aRef,
|
||||
const nsAString& aExpr)
|
||||
{
|
||||
if (mGenerationStarted)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsRefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
|
||||
if (!bindings) {
|
||||
bindings = new nsXMLBindingSet();
|
||||
if (!bindings || !mRuleToBindingsMap.Put(aRuleNode, bindings))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMXPathExpression> compiledexpr;
|
||||
nsresult rv =
|
||||
CreateExpression(aExpr, aRuleNode, getter_AddRefs(compiledexpr));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// aRef isn't currently used for XML query processors
|
||||
return bindings->AddBinding(aVar, compiledexpr);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::TranslateRef(nsISupports* aDatasource,
|
||||
const nsAString& aRefString,
|
||||
nsIXULTemplateResult** aRef)
|
||||
{
|
||||
*aRef = nsnull;
|
||||
|
||||
// the datasource is either a document or a DOM element
|
||||
nsCOMPtr<nsIDOMElement> rootElement;
|
||||
nsCOMPtr<nsIDOMDocument> doc = do_QueryInterface(aDatasource);
|
||||
if (doc)
|
||||
doc->GetDocumentElement(getter_AddRefs(rootElement));
|
||||
else
|
||||
rootElement = do_QueryInterface(aDatasource);
|
||||
|
||||
// if no root element, just return. The document may not have loaded yet
|
||||
if (!rootElement)
|
||||
return NS_OK;
|
||||
|
||||
nsXULTemplateResultXML* result =
|
||||
new nsXULTemplateResultXML(nsnull, rootElement, nsnull);
|
||||
NS_ENSURE_TRUE(result, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
*aRef = result;
|
||||
NS_ADDREF(*aRef);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
|
||||
nsIXULTemplateResult* aRight,
|
||||
nsIAtom* aVar,
|
||||
PRInt32* aResult)
|
||||
{
|
||||
*aResult = 0;
|
||||
|
||||
// XXXndeakin - bug 379745
|
||||
// it would be good for this to handle other types such as integers,
|
||||
// so that sorting can be optimized for different types.
|
||||
|
||||
nsAutoString leftVal;
|
||||
aLeft->GetBindingFor(aVar, leftVal);
|
||||
|
||||
nsAutoString rightVal;
|
||||
aRight->GetBindingFor(aVar, rightVal);
|
||||
|
||||
// currently templates always sort case-insensitive
|
||||
*aResult = ::Compare(leftVal, rightVal,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsXMLBindingSet*
|
||||
nsXULTemplateQueryProcessorXML::GetOptionalBindingsForRule(nsIDOMNode* aRuleNode)
|
||||
{
|
||||
return mRuleToBindingsMap.GetWeak(aRuleNode);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTemplateQueryProcessorXML::CreateExpression(const nsAString& aExpr,
|
||||
nsIDOMNode* aNode,
|
||||
nsIDOMXPathExpression** aCompiledExpr)
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathNSResolver> nsResolver;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
aNode->GetOwnerDocument(getter_AddRefs(doc));
|
||||
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> eval = do_QueryInterface(doc);
|
||||
if (eval) {
|
||||
nsresult rv =
|
||||
eval->CreateNSResolver(aNode, getter_AddRefs(nsResolver));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
return mEvaluator->CreateExpression(aExpr, nsResolver, aCompiledExpr);
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXULTemplateQueryProcessorXML_h__
|
||||
#define nsXULTemplateQueryProcessorXML_h__
|
||||
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsXMLBinding.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorXML;
|
||||
|
||||
#define NS_IXMLQUERY_IID \
|
||||
{0x0358d692, 0xccce, 0x4a97, \
|
||||
{ 0xb2, 0x51, 0xba, 0x8f, 0x17, 0x0f, 0x3b, 0x6f }}
|
||||
|
||||
class nsXMLQuery : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IXMLQUERY_IID)
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// return a weak reference to the processor the query was created from
|
||||
nsXULTemplateQueryProcessorXML* Processor() { return mProcessor; }
|
||||
|
||||
// return a weak reference t the member variable for the query
|
||||
nsIAtom* GetMemberVariable() { return mMemberVariable; }
|
||||
|
||||
// return a weak reference to the expression used to generate results
|
||||
nsIDOMXPathExpression* GetResultsExpression() { return mResultsExpr; }
|
||||
|
||||
// return a weak reference to the additional required bindings
|
||||
nsXMLBindingSet* GetBindingSet() { return mRequiredBindings; }
|
||||
|
||||
// add a required binding for the query
|
||||
nsresult
|
||||
AddBinding(nsIAtom* aVar, nsIDOMXPathExpression* aExpr)
|
||||
{
|
||||
if (!mRequiredBindings) {
|
||||
mRequiredBindings = new nsXMLBindingSet();
|
||||
NS_ENSURE_TRUE(mRequiredBindings, NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
return mRequiredBindings->AddBinding(aVar, aExpr);
|
||||
}
|
||||
|
||||
nsXMLQuery(nsXULTemplateQueryProcessorXML* aProcessor,
|
||||
nsIAtom* aMemberVariable,
|
||||
nsIDOMXPathExpression* aResultsExpr)
|
||||
: mProcessor(aProcessor),
|
||||
mMemberVariable(aMemberVariable),
|
||||
mResultsExpr(aResultsExpr)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
nsXULTemplateQueryProcessorXML* mProcessor;
|
||||
|
||||
nsCOMPtr<nsIAtom> mMemberVariable;
|
||||
|
||||
nsCOMPtr<nsIDOMXPathExpression> mResultsExpr;
|
||||
|
||||
nsRefPtr<nsXMLBindingSet> mRequiredBindings;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsXMLQuery, NS_IXMLQUERY_IID)
|
||||
|
||||
class nsXULTemplateResultSetXML : public nsISimpleEnumerator
|
||||
{
|
||||
private:
|
||||
|
||||
// reference back to the query
|
||||
nsCOMPtr<nsXMLQuery> mQuery;
|
||||
|
||||
// the binding set created from <assign> nodes
|
||||
nsRefPtr<nsXMLBindingSet> mBindingSet;
|
||||
|
||||
// set of results contained in this enumerator
|
||||
nsCOMPtr<nsIDOMXPathResult> mResults;
|
||||
|
||||
// current position within the list of results
|
||||
PRUint32 mPosition;
|
||||
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator interface
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsXULTemplateResultSetXML(nsXMLQuery* aQuery,
|
||||
nsIDOMXPathResult* aResults,
|
||||
nsXMLBindingSet* aBindingSet)
|
||||
: mQuery(aQuery),
|
||||
mBindingSet(aBindingSet),
|
||||
mResults(aResults),
|
||||
mPosition(0)
|
||||
{}
|
||||
};
|
||||
|
||||
class nsXULTemplateQueryProcessorXML : public nsIXULTemplateQueryProcessor
|
||||
{
|
||||
public:
|
||||
|
||||
nsXULTemplateQueryProcessorXML()
|
||||
: mGenerationStarted(PR_FALSE)
|
||||
{}
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIXULTemplateQueryProcessor interface
|
||||
NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR
|
||||
|
||||
nsXMLBindingSet*
|
||||
GetOptionalBindingsForRule(nsIDOMNode* aRuleNode);
|
||||
|
||||
// create an XPath expression from aExpr, using aNode for
|
||||
// resolving namespaces
|
||||
nsresult
|
||||
CreateExpression(const nsAString& aExpr,
|
||||
nsIDOMNode* aNode,
|
||||
nsIDOMXPathExpression** aCompiledExpr);
|
||||
|
||||
private:
|
||||
|
||||
PRBool mGenerationStarted;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, nsXMLBindingSet> mRuleToBindingsMap;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> mRoot;
|
||||
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> mEvaluator;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsXULTemplateQueryProcessorXML_h__
|
|
@ -0,0 +1,210 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
#include "nsIRDFService.h"
|
||||
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
#include "nsXMLBinding.h"
|
||||
|
||||
static PRUint32 sTemplateId = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXULTemplateResultXML, nsIXULTemplateResult)
|
||||
|
||||
nsXULTemplateResultXML::nsXULTemplateResultXML(nsXMLQuery* aQuery,
|
||||
nsIDOMNode* aNode,
|
||||
nsXMLBindingSet* aBindings)
|
||||
: mId(++sTemplateId), mQuery(aQuery), mNode(aNode)
|
||||
{
|
||||
if (aBindings)
|
||||
mRequiredValues.SetBindingSet(aBindings);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetIsContainer(PRBool* aIsContainer)
|
||||
{
|
||||
// a node is considered a container if it has children
|
||||
if (mNode)
|
||||
mNode->HasChildNodes(aIsContainer);
|
||||
else
|
||||
*aIsContainer = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetIsEmpty(PRBool* aIsEmpty)
|
||||
{
|
||||
// a node is considered empty if it has no elements as children
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mNode);
|
||||
if (content) {
|
||||
PRUint32 count = content->GetChildCount();
|
||||
for (PRUint32 c = 0; c < count; c++) {
|
||||
if (content->GetChildAt(c)->IsNodeOfType(nsIContent::eELEMENT)) {
|
||||
*aIsEmpty = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aIsEmpty = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetMayProcessChildren(PRBool* aMayProcessChildren)
|
||||
{
|
||||
*aMayProcessChildren = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetId(nsAString& aId)
|
||||
{
|
||||
nsAutoString rowid(NS_LITERAL_STRING("row"));
|
||||
rowid.AppendInt(mId);
|
||||
aId.Assign(rowid);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetResource(nsIRDFResource** aResource)
|
||||
{
|
||||
*aResource = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetBindingFor(nsIAtom* aVar, nsAString& aValue)
|
||||
{
|
||||
// get the position of the atom in the variables table
|
||||
nsXMLBinding* binding;
|
||||
|
||||
PRInt32 idx = mRequiredValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx >= 0) {
|
||||
mRequiredValues.GetStringAssignmentFor(this, binding, idx, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
idx = mOptionalValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx >= 0) {
|
||||
mOptionalValues.GetStringAssignmentFor(this, binding, idx, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// if the variable is not bound, just use the variable name as the name of
|
||||
// an attribute to retrieve
|
||||
nsAutoString attr;
|
||||
aVar->ToString(attr);
|
||||
|
||||
if (attr.Length() > 1) {
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(mNode);
|
||||
if (element)
|
||||
return element->GetAttribute(Substring(attr, 1), aValue);
|
||||
}
|
||||
|
||||
aValue.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetBindingObjectFor(nsIAtom* aVar, nsISupports** aValue)
|
||||
{
|
||||
nsXMLBinding* binding;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
|
||||
if (mQuery && aVar == mQuery->GetMemberVariable()) {
|
||||
node = mNode;
|
||||
}
|
||||
else {
|
||||
PRInt32 idx = mRequiredValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx > 0) {
|
||||
mRequiredValues.GetNodeAssignmentFor(this, binding, idx,
|
||||
getter_AddRefs(node));
|
||||
}
|
||||
else {
|
||||
idx = mOptionalValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx > 0) {
|
||||
mOptionalValues.GetNodeAssignmentFor(this, binding, idx,
|
||||
getter_AddRefs(node));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aValue = node;
|
||||
NS_IF_ADDREF(*aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::RuleMatched(nsISupports* aQueryNode,
|
||||
nsIDOMNode* aRuleNode)
|
||||
{
|
||||
// when a rule matches, set the bindings that must be used.
|
||||
nsXULTemplateQueryProcessorXML* processor = mQuery ? mQuery->Processor() :
|
||||
nsnull;
|
||||
if (processor) {
|
||||
nsXMLBindingSet* bindings =
|
||||
processor->GetOptionalBindingsForRule(aRuleNode);
|
||||
if (bindings)
|
||||
mOptionalValues.SetBindingSet(bindings);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::HasBeenRemoved()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTemplateResultXML::GetNode(nsIDOMNode** aNode)
|
||||
{
|
||||
*aNode = mNode;
|
||||
NS_IF_ADDREF(*aNode);
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Neil Deakin
|
||||
* Portions created by the Initial Developer are Copyright (C) 2006
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXULTemplateResultXML_h__
|
||||
#define nsXULTemplateResultXML_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
|
||||
/**
|
||||
* An single result of an query
|
||||
*/
|
||||
class nsXULTemplateResultXML : public nsIXULTemplateResult
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIXULTEMPLATERESULT
|
||||
|
||||
nsXULTemplateResultXML(nsXMLQuery* aQuery,
|
||||
nsIDOMNode* aNode,
|
||||
nsXMLBindingSet* aBindings);
|
||||
|
||||
~nsXULTemplateResultXML() {}
|
||||
|
||||
void GetNode(nsIDOMNode** aNode);
|
||||
|
||||
protected:
|
||||
|
||||
// result id
|
||||
PRUint32 mId;
|
||||
|
||||
// query that generated the result
|
||||
nsCOMPtr<nsXMLQuery> mQuery;
|
||||
|
||||
// context node in datasource
|
||||
nsCOMPtr<nsIDOMNode> mNode;
|
||||
|
||||
// assignments in query
|
||||
nsXMLBindingValues mRequiredValues;
|
||||
|
||||
// extra assignments made by rules (<binding> tags)
|
||||
nsXMLBindingValues mOptionalValues;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateResultXML_h__
|
|
@ -1374,7 +1374,8 @@ nsXULTreeBuilder::RebuildAll()
|
|||
mRoot->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, ref);
|
||||
|
||||
if (! ref.IsEmpty()) {
|
||||
rv = mQueryProcessor->TranslateRef(mDB, ref, getter_AddRefs(mRootResult));
|
||||
rv = mQueryProcessor->TranslateRef(mDataSource, ref,
|
||||
getter_AddRefs(mRootResult));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
|
@ -1577,7 +1578,7 @@ nsXULTreeBuilder::OpenSubtreeForQuerySet(nsTreeRows::Subtree* aSubtree,
|
|||
PRInt32 count = *aDelta;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> results;
|
||||
nsresult rv = mQueryProcessor->GenerateResults(mDB, aResult,
|
||||
nsresult rv = mQueryProcessor->GenerateResults(mDataSource, aResult,
|
||||
aQuerySet->mCompiledQuery,
|
||||
getter_AddRefs(results));
|
||||
if (NS_FAILED(rv))
|
||||
|
@ -1812,7 +1813,9 @@ nsXULTreeBuilder::Compare(const void* aLeft, const void* aRight, void* aClosure)
|
|||
PRInt32
|
||||
nsXULTreeBuilder::CompareResults(nsIXULTemplateResult* aLeft, nsIXULTemplateResult* aRight)
|
||||
{
|
||||
if (mSortDirection == eDirection_Natural) {
|
||||
// this is an extra check done for RDF queries such that results appear in
|
||||
// the order they appear in their containing Seq
|
||||
if (mSortDirection == eDirection_Natural && mDB) {
|
||||
// If the sort order is ``natural'', then see if the container
|
||||
// is an RDF sequence. If so, we'll try to use the ordinal
|
||||
// properties to determine order.
|
||||
|
|
Загрузка…
Ссылка в новой задаче