michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIDOMNode.h" michael@0: #include "nsIDOMElement.h" michael@0: #include "nsIContent.h" michael@0: michael@0: #include "nsIRDFService.h" michael@0: michael@0: #include "nsXULTemplateResultXML.h" michael@0: #include "nsXMLBinding.h" michael@0: michael@0: static uint32_t sTemplateId = 0; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsXULTemplateResultXML, nsIXULTemplateResult) michael@0: michael@0: nsXULTemplateResultXML::nsXULTemplateResultXML(nsXMLQuery* aQuery, michael@0: nsIDOMNode* aNode, michael@0: nsXMLBindingSet* aBindings) michael@0: : mQuery(aQuery), mNode(aNode) michael@0: { michael@0: nsCOMPtr content = do_QueryInterface(mNode); michael@0: michael@0: // If the node has an id, create the uri from it. Otherwise, there isn't michael@0: // anything to identify the node with so just use a somewhat random number. michael@0: nsCOMPtr id = content->GetID(); michael@0: if (id) { michael@0: nsCOMPtr uri = content->GetBaseURI(); michael@0: nsAutoCString spec; michael@0: uri->GetSpec(spec); michael@0: michael@0: mId = NS_ConvertUTF8toUTF16(spec); michael@0: michael@0: nsAutoString idstr; michael@0: id->ToString(idstr); michael@0: mId += NS_LITERAL_STRING("#") + idstr; michael@0: } michael@0: else { michael@0: nsAutoString rowid(NS_LITERAL_STRING("row")); michael@0: rowid.AppendInt(++sTemplateId); michael@0: mId.Assign(rowid); michael@0: } michael@0: michael@0: if (aBindings) michael@0: mRequiredValues.SetBindingSet(aBindings); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetIsContainer(bool* aIsContainer) michael@0: { michael@0: // a node is considered a container if it has children michael@0: if (mNode) michael@0: mNode->HasChildNodes(aIsContainer); michael@0: else michael@0: *aIsContainer = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetIsEmpty(bool* aIsEmpty) michael@0: { michael@0: // a node is considered empty if it has no elements as children michael@0: nsCOMPtr content = do_QueryInterface(mNode); michael@0: if (content) { michael@0: for (nsIContent* child = content->GetFirstChild(); michael@0: child; michael@0: child = child->GetNextSibling()) { michael@0: if (child->IsElement()) { michael@0: *aIsEmpty = false; michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: michael@0: *aIsEmpty = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetMayProcessChildren(bool* aMayProcessChildren) michael@0: { michael@0: *aMayProcessChildren = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetId(nsAString& aId) michael@0: { michael@0: aId = mId; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetResource(nsIRDFResource** aResource) michael@0: { michael@0: *aResource = nullptr; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetType(nsAString& aType) michael@0: { michael@0: aType.Truncate(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetBindingFor(nsIAtom* aVar, nsAString& aValue) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aVar); michael@0: michael@0: // get the position of the atom in the variables table michael@0: nsXMLBinding* binding; michael@0: michael@0: int32_t idx = mRequiredValues.LookupTargetIndex(aVar, &binding); michael@0: if (idx >= 0) { michael@0: mRequiredValues.GetStringAssignmentFor(this, binding, idx, aValue); michael@0: return NS_OK; michael@0: } michael@0: michael@0: idx = mOptionalValues.LookupTargetIndex(aVar, &binding); michael@0: if (idx >= 0) { michael@0: mOptionalValues.GetStringAssignmentFor(this, binding, idx, aValue); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // if the variable is not bound, just use the variable name as the name of michael@0: // an attribute to retrieve michael@0: nsAutoString attr; michael@0: aVar->ToString(attr); michael@0: michael@0: if (attr.Length() > 1) { michael@0: nsCOMPtr element = do_QueryInterface(mNode); michael@0: if (element) michael@0: return element->GetAttribute(Substring(attr, 1), aValue); michael@0: } michael@0: michael@0: aValue.Truncate(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::GetBindingObjectFor(nsIAtom* aVar, nsISupports** aValue) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aVar); michael@0: michael@0: nsXMLBinding* binding; michael@0: nsCOMPtr node; michael@0: michael@0: if (mQuery && aVar == mQuery->GetMemberVariable()) { michael@0: node = mNode; michael@0: } michael@0: else { michael@0: int32_t idx = mRequiredValues.LookupTargetIndex(aVar, &binding); michael@0: if (idx > 0) { michael@0: mRequiredValues.GetNodeAssignmentFor(this, binding, idx, michael@0: getter_AddRefs(node)); michael@0: } michael@0: else { michael@0: idx = mOptionalValues.LookupTargetIndex(aVar, &binding); michael@0: if (idx > 0) { michael@0: mOptionalValues.GetNodeAssignmentFor(this, binding, idx, michael@0: getter_AddRefs(node)); michael@0: } michael@0: } michael@0: } michael@0: michael@0: *aValue = node; michael@0: NS_IF_ADDREF(*aValue); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::RuleMatched(nsISupports* aQueryNode, michael@0: nsIDOMNode* aRuleNode) michael@0: { michael@0: // when a rule matches, set the bindings that must be used. michael@0: nsXULTemplateQueryProcessorXML* processor = mQuery ? mQuery->Processor() : michael@0: nullptr; michael@0: if (processor) { michael@0: nsXMLBindingSet* bindings = michael@0: processor->GetOptionalBindingsForRule(aRuleNode); michael@0: if (bindings) michael@0: mOptionalValues.SetBindingSet(bindings); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXULTemplateResultXML::HasBeenRemoved() michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsXULTemplateResultXML::GetNode(nsIDOMNode** aNode) michael@0: { michael@0: *aNode = mNode; michael@0: NS_IF_ADDREF(*aNode); michael@0: }