mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1425356 - remove XUL template support, r=bz
MozReview-Commit-ID: HdBoQ15DFOu --HG-- rename : dom/xul/templates/nsIXULSortService.idl => dom/xul/nsIXULSortService.idl rename : dom/xul/templates/nsXULContentUtils.cpp => dom/xul/nsXULContentUtils.cpp rename : dom/xul/templates/nsXULContentUtils.h => dom/xul/nsXULContentUtils.h rename : dom/xul/templates/nsXULSortService.cpp => dom/xul/nsXULSortService.cpp rename : dom/xul/templates/nsXULSortService.h => dom/xul/nsXULSortService.h extra : rebase_source : e3f3504c529e7bd9aa52aecf34b94bb5b0ff92b4
This commit is contained in:
parent
e8c1471db1
commit
a8bb5924c6
@ -340,7 +340,6 @@
|
||||
@RESPATH@/components/xpconnect.xpt
|
||||
@RESPATH@/components/xulapp.xpt
|
||||
@RESPATH@/components/xul.xpt
|
||||
@RESPATH@/components/xultmpl.xpt
|
||||
@RESPATH@/components/zipwriter.xpt
|
||||
@RESPATH@/components/telemetry.xpt
|
||||
|
||||
|
@ -1274,12 +1274,6 @@ var interfaceNamesInGlobalScope =
|
||||
{name: "XULElement", xbl: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XULLabeledControlElement", xbl: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XULTemplateBuilder", xbl: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XULTreeBuilder", xbl: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "XULTreeBuilderObserver", xbl: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
];
|
||||
// IMPORTANT: Do not change the list above without review from a DOM peer!
|
||||
|
@ -92,4 +92,3 @@ XMLHttpRequest implements LegacyQueryInterface;
|
||||
XMLHttpRequestUpload implements LegacyQueryInterface;
|
||||
XMLSerializer implements LegacyQueryInterface;
|
||||
XPathEvaluator implements LegacyQueryInterface;
|
||||
XULTemplateBuilder implements LegacyQueryInterface;
|
||||
|
@ -5,8 +5,6 @@
|
||||
*/
|
||||
|
||||
interface XULControllers;
|
||||
interface MozRDFCompositeDataSource;
|
||||
interface MozRDFResource;
|
||||
|
||||
[HTMLConstructor, Func="IsChromeOrXBL"]
|
||||
interface XULElement : Element {
|
||||
@ -68,12 +66,6 @@ interface XULElement : Element {
|
||||
[SetterThrows]
|
||||
attribute DOMString top;
|
||||
|
||||
// XUL Template Builder
|
||||
[SetterThrows]
|
||||
attribute DOMString datasources;
|
||||
[SetterThrows]
|
||||
attribute DOMString ref;
|
||||
|
||||
// Tooltip and status info
|
||||
[SetterThrows]
|
||||
attribute DOMString tooltipText;
|
||||
@ -86,10 +78,6 @@ interface XULElement : Element {
|
||||
|
||||
attribute boolean allowEvents;
|
||||
|
||||
readonly attribute MozRDFCompositeDataSource? database;
|
||||
readonly attribute XULTemplateBuilder? builder;
|
||||
[Throws]
|
||||
readonly attribute MozRDFResource? resource;
|
||||
[Throws, ChromeOnly]
|
||||
readonly attribute XULControllers controllers;
|
||||
[Throws]
|
||||
|
@ -1,398 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
interface MozRDFCompositeDataSource;
|
||||
interface MozRDFResource;
|
||||
interface nsISupports;
|
||||
interface XULTemplateResult;
|
||||
interface XULTemplateRuleFilter;
|
||||
|
||||
callback interface XULBuilderListener
|
||||
{
|
||||
void willRebuild(XULTemplateBuilder aBuilder);
|
||||
void didRebuild(XULTemplateBuilder aBuilder);
|
||||
};
|
||||
|
||||
/**
|
||||
* A template builder, given an input source of data, a template, and a
|
||||
* reference point, generates a list of results from the input, and copies
|
||||
* part of the template for each result. Templates may generate content
|
||||
* recursively, using the same template, but with the previous iteration's
|
||||
* results as the reference point. As an example, for an XML datasource the
|
||||
* initial reference point would be a specific node in the DOM tree and a
|
||||
* template might generate a list of all child nodes. For the next iteration,
|
||||
* those children would be used to generate output for their child nodes and
|
||||
* so forth.
|
||||
*
|
||||
* A template builder is attached to a single DOM node; this node is called
|
||||
* the root node and is expected to contain a XUL template element as a direct
|
||||
* child. Different template builders may be specialized in the manner in
|
||||
* which they generate and display the resulting content from the template.
|
||||
*
|
||||
* The structure of a template is as follows:
|
||||
*
|
||||
* <rootnode datasources="" ref="">
|
||||
* <template>
|
||||
* <queryset>
|
||||
* <query>
|
||||
* </query>
|
||||
* <rule>
|
||||
* <conditions>...</conditions>
|
||||
* <bindings>...</bindings>
|
||||
* <action>...</action>
|
||||
* </rule>
|
||||
* </queryset>
|
||||
* </template>
|
||||
* </rootnode>
|
||||
*
|
||||
* The datasources attribute on the root node is used to identify the source
|
||||
* of data to be used. The ref attribute is used to specify the reference
|
||||
* point for the query. Currently, the datasource will either be an
|
||||
* nsIRDFDataSource or a DOM node. In the future, other datasource types may
|
||||
* be used.
|
||||
*
|
||||
* The <queryset> element contains a single query and one or more <rule>
|
||||
* elements. There may be more than one <queryset> if multiple queries are
|
||||
* desired, and this element is optional if only one query is needed -- in
|
||||
* that case the <query> and <rule>s are allowed to be children of the
|
||||
* <template> node
|
||||
*
|
||||
* The contents of the query are processed by a separate component called a
|
||||
* query processor. This query processor is expected to use this query to
|
||||
* generate results when asked by the template builder. The template builder
|
||||
* then generates output for each result based on the <rule> elements.
|
||||
*
|
||||
* This allows the query processor to be specific to a particular kind of
|
||||
* input data or query syntax, while the template builder remains independent
|
||||
* of the kind of data being used. Due to this, the query processor will be
|
||||
* supplied with the datasource and query which the template builder handles
|
||||
* in an opaque way, while the query processor handles these more
|
||||
* specifically.
|
||||
*
|
||||
* Results implement the nsIXULTemplateResult interface and may be identified
|
||||
* by an id which must be unique within a given set of query results.
|
||||
*
|
||||
* Each query may be accompanied by one or more <rule> elements. These rules
|
||||
* are evaluated by the template builder for each result produced by the
|
||||
* query. A rule consists of conditions that cause a rule to be either
|
||||
* accepted or rejected. The condition syntax allows for common conditional
|
||||
* handling; additional filtering may be applied by adding a custom filter
|
||||
* to a rule with the builder's addRuleFilter method.
|
||||
*
|
||||
* If a result passes a rule's conditions, this is considered a match, and the
|
||||
* content within the rule's <action> body is inserted as a sibling of the
|
||||
* <template>, assuming the template builder creates real DOM content. Only
|
||||
* one rule will match a result. For a tree builder, for example, the content
|
||||
* within the action body is used to create the tree rows instead. A matching
|
||||
* result must have its ruleMatched method called. When a result no longer
|
||||
* matches, the result's hasBeenRemoved method must be called.
|
||||
*
|
||||
* Optionally, the rule may have a <bindings> section which may be used to
|
||||
* define additional variables to be used within an action body. Each of these
|
||||
* declared bindings must be supplied to the query processor via its
|
||||
* addBinding method. The bindings are evaluated after a rule has matched.
|
||||
*
|
||||
* Templates may generate content recursively, using the previous iteration's
|
||||
* results as reference point to invoke the same queries. Since the reference
|
||||
* point is different, different output will typically be generated.
|
||||
*
|
||||
* The reference point nsIXULTemplateResult object for the first iteration is
|
||||
* determined by calling the query processor's translateRef method using the
|
||||
* value of the root node's ref attribute. This object may be retrieved later
|
||||
* via the builder's rootResult property.
|
||||
*
|
||||
* For convenience, each reference point as well as all results implement the
|
||||
* nsIXULTemplateResult interface, allowing the result objects from each
|
||||
* iteration to be used directly as the reference points for the next
|
||||
* iteration.
|
||||
*
|
||||
* When using multiple queries, each may generate results with the same id.
|
||||
* More than one of these results may match one of the rules in their
|
||||
* respective queries, however only the result for the earliest matching query
|
||||
* in the template becomes the active match and generates output. The
|
||||
* addResult, removeResult, replaceResult and resultBindingChanged methods may
|
||||
* be called by the query processor to indicate that the set of valid results
|
||||
* has changed, such that a different query may match. If a different match
|
||||
* would become active, the content for the existing match is removed and the
|
||||
* content for the new match is generated. A query processor is not required
|
||||
* to provide any support for updating results after they have been generated.
|
||||
*
|
||||
* See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
|
||||
*/
|
||||
[Func="IsChromeOrXBL"]
|
||||
interface XULTemplateBuilder
|
||||
{
|
||||
/**
|
||||
* The root node in the DOM to which this builder is attached.
|
||||
*/
|
||||
readonly attribute Element? root;
|
||||
|
||||
/**
|
||||
* The opaque datasource object that is used for the template. This object
|
||||
* is created by the getDataSource method of the query processor. May be
|
||||
* null if the datasource has not been loaded yet. Set this attribute to
|
||||
* use a different datasource and rebuild the template.
|
||||
*
|
||||
* For an RDF datasource, this will be the same as the database. For XML
|
||||
* this will be the nsIDOMNode for the datasource document or node for
|
||||
* an inline reference (such as #name). Other query processors may use
|
||||
* other types for the datasource.
|
||||
*/
|
||||
[SetterThrows]
|
||||
attribute nsISupports? datasource;
|
||||
|
||||
/**
|
||||
* The composite datasource that the template builder observes
|
||||
* and uses to create content. This is used only for RDF queries and is
|
||||
* maintained for backwards compatibility. It will be the same object as
|
||||
* the datasource property. For non-RDF queries, it will always be null.
|
||||
*/
|
||||
readonly attribute MozRDFCompositeDataSource? database;
|
||||
|
||||
/**
|
||||
* The virtual result representing the starting reference point,
|
||||
* determined by calling the query processor's translateRef method
|
||||
* with the root node's ref attribute as an argument.
|
||||
*/
|
||||
readonly attribute XULTemplateResult? rootResult;
|
||||
|
||||
/**
|
||||
* Force the template builder to rebuild its content. All existing content
|
||||
* will be removed first. The query processor's done() method will be
|
||||
* invoked during cleanup, followed by its initializeForBuilding method
|
||||
* when the content is to be regenerated.
|
||||
*
|
||||
*/
|
||||
[Throws]
|
||||
void rebuild();
|
||||
|
||||
/**
|
||||
* Reload any of our RDF datasources that support nsIRDFRemoteDatasource.
|
||||
*
|
||||
* @note This is a temporary hack so that remote-XUL authors can
|
||||
* reload remote datasources. When RDF becomes remote-scriptable,
|
||||
* this will no longer be necessary.
|
||||
*/
|
||||
[Throws]
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Inform the template builder that a new result is available. The builder
|
||||
* will add this result to the set of results. The query node that the
|
||||
* new result applies to must be specified using the aQueryNode parameter.
|
||||
*
|
||||
* The builder will apply the rules associated with the query to the new
|
||||
* result, unless a result with the same id from an earlier query
|
||||
* supersedes it, and the result's RuleMatched method will be called if it
|
||||
* matches.
|
||||
*
|
||||
* @param aResult the result to add
|
||||
* @param aQueryNode the query that the result applies to
|
||||
*/
|
||||
[Throws]
|
||||
void addResult(XULTemplateResult aResult, Node aQueryNode);
|
||||
|
||||
/**
|
||||
* Inform the template builder that a result no longer applies. The builder
|
||||
* will call the remove content generated for the result, if any. If a
|
||||
* different query would then match instead, it will become the active
|
||||
* match. This method will have no effect if the result isn't known to the
|
||||
* builder.
|
||||
*
|
||||
* @param aResult the result to remove
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aResult is null
|
||||
*/
|
||||
[Throws]
|
||||
void removeResult(XULTemplateResult aResult);
|
||||
|
||||
/**
|
||||
* Inform the template builder that one result should be replaced with
|
||||
* another. Both the old result (aOldResult) and the new result
|
||||
* (aNewResult) must have the same id. The query node that the new result
|
||||
* applies to must be specified using the aQueryNode parameter.
|
||||
*
|
||||
* This method is expected to have the same effect as calling both
|
||||
* removeResult for the old result and addResult for the new result.
|
||||
*
|
||||
* @param aOldResult the old result
|
||||
* @param aNewResult the new result
|
||||
* @param aQueryNode the query that the new result applies to
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if either argument is null, or
|
||||
* NS_ERROR_INVALID_ARG if the ids don't match
|
||||
*/
|
||||
[Throws]
|
||||
void replaceResult(XULTemplateResult aOldResult,
|
||||
XULTemplateResult aNewResult,
|
||||
Node aQueryNode);
|
||||
|
||||
/**
|
||||
* Inform the template builder that one or more of the optional bindings
|
||||
* for a result has changed. In this case, the rules are not reapplied as
|
||||
* it is expected that the same rule will still apply. The builder will
|
||||
* resynchronize any variables that are referenced in the action body.
|
||||
*
|
||||
* @param aResult the result to change
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aResult is null
|
||||
*/
|
||||
[Throws]
|
||||
void resultBindingChanged(XULTemplateResult aResult);
|
||||
|
||||
/**
|
||||
* Return the result for a given id. Only one such result is returned and
|
||||
* is always the result with that id associated with the active match.
|
||||
* This method will return null is there is no result for the id.
|
||||
*
|
||||
* @param aId the id to return the result for
|
||||
*/
|
||||
[Throws]
|
||||
XULTemplateResult? getResultForId(DOMString aId);
|
||||
|
||||
/**
|
||||
* Retrieve the result corresponding to a generated element, or null is
|
||||
* there isn't one.
|
||||
*
|
||||
* @param aContent element to result the result of
|
||||
*/
|
||||
XULTemplateResult? getResultForContent(Element aElement);
|
||||
|
||||
/**
|
||||
* Returns true if the node has content generated for it. This method is
|
||||
* intended to be called only by the RDF query processor. If aTag is set,
|
||||
* the content must have a tag name that matches aTag. aTag may be ignored
|
||||
* for builders that don't generate real DOM content.
|
||||
*
|
||||
* @param aNode node to check
|
||||
* @param aTag tag that must match
|
||||
*/
|
||||
[Throws]
|
||||
boolean hasGeneratedContent(MozRDFResource aNode, DOMString? aTag);
|
||||
|
||||
/**
|
||||
* Adds a rule filter for a given rule, which may be used for specialized
|
||||
* rule filtering. Any existing filter on the rule is removed. The default
|
||||
* conditions specified inside the <rule> tag are applied before the
|
||||
* rule filter is applied, meaning that the filter may be used to further
|
||||
* filter out results but not reaccept results that have already been
|
||||
* rejected.
|
||||
*
|
||||
* @param aRule the rule to apply the filter to
|
||||
* @param aFilter the filter to add
|
||||
*/
|
||||
[Throws]
|
||||
void addRuleFilter(Node aRule, XULTemplateRuleFilter aFilter);
|
||||
|
||||
/**
|
||||
* Add a listener to this template builder. The template builder
|
||||
* holds a strong reference to the listener.
|
||||
*/
|
||||
void addListener(XULBuilderListener aListener);
|
||||
|
||||
/**
|
||||
* Remove a listener from this template builder.
|
||||
*/
|
||||
void removeListener(XULBuilderListener aListener);
|
||||
};
|
||||
|
||||
/**
|
||||
* XULTreeBuilderObserver
|
||||
* This interface allows clients of the XULTreeBuilder to define domain
|
||||
* specific handling of specific nsITreeView methods that
|
||||
* XULTreeBuilder does not implement.
|
||||
*/
|
||||
[Func="IsChromeOrXBL"]
|
||||
callback interface XULTreeBuilderObserver
|
||||
{
|
||||
const long DROP_BEFORE = -1;
|
||||
const long DROP_ON = 0;
|
||||
const long DROP_AFTER = 1;
|
||||
/**
|
||||
* Methods used by the drag feedback code to determine if a drag is
|
||||
* allowable at the current location. To get the behavior where drops are
|
||||
* only allowed on items, such as the mailNews folder pane, always return
|
||||
* false when the orientation is not DROP_ON.
|
||||
*/
|
||||
boolean canDrop(long index, long orientation, DataTransfer? dataTransfer);
|
||||
|
||||
/**
|
||||
* Called when the user drops something on this view. The |orientation|
|
||||
* param specifies before/on/after the given |row|.
|
||||
*/
|
||||
void onDrop(long row, long orientation, DataTransfer? dataTransfer);
|
||||
|
||||
/**
|
||||
* Called when an item is opened or closed.
|
||||
*/
|
||||
void onToggleOpenState(long index);
|
||||
|
||||
/**
|
||||
* Called when a header is clicked.
|
||||
*/
|
||||
void onCycleHeader(DOMString colID, Element? elt);
|
||||
|
||||
/**
|
||||
* Called when a cell in a non-selectable cycling column (e.g.
|
||||
* unread/flag/etc.) is clicked.
|
||||
*/
|
||||
void onCycleCell(long row, DOMString colID);
|
||||
|
||||
/**
|
||||
* Called when selection in the tree changes
|
||||
*/
|
||||
void onSelectionChanged();
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on the selection.
|
||||
* The tree will automatically invoke this method when certain keys
|
||||
* are pressed. For example, when the DEL key is pressed, performAction
|
||||
* will be called with the "delete" string.
|
||||
*/
|
||||
void onPerformAction(DOMString action);
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on a specific row.
|
||||
*/
|
||||
void onPerformActionOnRow(DOMString action, long row);
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on a specific cell.
|
||||
*/
|
||||
void onPerformActionOnCell(DOMString action, long row, DOMString colID);
|
||||
};
|
||||
|
||||
[Func="IsChromeOrXBL"]
|
||||
interface XULTreeBuilder : XULTemplateBuilder
|
||||
{
|
||||
/**
|
||||
* Retrieve the RDF resource associated with the specified row.
|
||||
*/
|
||||
[Throws]
|
||||
MozRDFResource? getResourceAtIndex(long aRowIndex);
|
||||
|
||||
/**
|
||||
* Retrieve the index associated with specified RDF resource.
|
||||
*/
|
||||
[Throws]
|
||||
long getIndexOfResource(MozRDFResource resource);
|
||||
|
||||
/**
|
||||
* Add a Tree Builder Observer to handle Tree View
|
||||
* methods that the base builder does not implement.
|
||||
*/
|
||||
void addObserver(XULTreeBuilderObserver aObserver);
|
||||
|
||||
/**
|
||||
* Remove an Tree Builder Observer.
|
||||
*/
|
||||
void removeObserver(XULTreeBuilderObserver aObserver);
|
||||
|
||||
/**
|
||||
* Sort the contents of the tree using the specified column.
|
||||
*/
|
||||
void sort(Element aColumnElement);
|
||||
};
|
||||
XULTreeBuilder implements TreeView;
|
@ -971,7 +971,6 @@ WEBIDL_FILES = [
|
||||
'XULCommandEvent.webidl',
|
||||
'XULDocument.webidl',
|
||||
'XULElement.webidl',
|
||||
'XULTemplateBuilder.webidl',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_WEBRTC']:
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "nsXULCommandDispatcher.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "rdf.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsXBLService.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
@ -59,6 +58,7 @@
|
||||
#include "nsIObjectInputStream.h"
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsContentList.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
@ -95,8 +95,6 @@
|
||||
#include "xpcpublic.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
#include "mozilla/StyleSheetInlines.h"
|
||||
#include "nsXULTemplateBuilder.h"
|
||||
#include "nsXULTreeBuilder.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
@ -197,7 +195,6 @@ XULDocument::XULDocument(void)
|
||||
mDocumentLoaded(false),
|
||||
mStillWalking(false),
|
||||
mRestrictPersistence(false),
|
||||
mTemplateBuilderTable(nullptr),
|
||||
mPendingSheets(0),
|
||||
mDocLWTheme(Doc_Theme_Uninitialized),
|
||||
mState(eState_Master),
|
||||
@ -237,8 +234,6 @@ XULDocument::~XULDocument()
|
||||
// Destroy our broadcaster map.
|
||||
delete mBroadcasterMap;
|
||||
|
||||
delete mTemplateBuilderTable;
|
||||
|
||||
Preferences::UnregisterCallback(XULDocument::DirectionChanged,
|
||||
"intl.uidirection", this);
|
||||
|
||||
@ -285,19 +280,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULDocument, XMLDocument)
|
||||
// XXX tmp->mForwardReferences?
|
||||
// XXX tmp->mContextStack?
|
||||
|
||||
// An element will only have a template builder as long as it's in the
|
||||
// document, so we'll traverse the table here instead of from the element.
|
||||
if (tmp->mTemplateBuilderTable) {
|
||||
for (auto iter = tmp->mTemplateBuilderTable->Iter();
|
||||
!iter.Done();
|
||||
iter.Next()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mTemplateBuilderTable key");
|
||||
cb.NoteXPCOMChild(iter.Key());
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mTemplateBuilderTable value");
|
||||
cb.NoteXPCOMChild(iter.UserData());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCurrentPrototype)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMasterPrototype)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCommandDispatcher)
|
||||
@ -323,9 +305,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(XULDocument, XMLDocument)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(XULDocument, XMLDocument)
|
||||
delete tmp->mTemplateBuilderTable;
|
||||
tmp->mTemplateBuilderTable = nullptr;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCommandDispatcher)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mLocalStore)
|
||||
//XXX We should probably unlink all the objects we traverse.
|
||||
@ -1667,26 +1646,6 @@ XULDocument::AddElementToDocumentPost(Element* aElement)
|
||||
nsXBLService::AttachGlobalKeyHandler(aElement);
|
||||
}
|
||||
|
||||
// See if we need to attach a XUL template to this node
|
||||
bool needsHookup;
|
||||
nsresult rv = CheckTemplateBuilderHookup(aElement, &needsHookup);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (needsHookup) {
|
||||
if (mResolutionPhase == nsForwardReference::eDone) {
|
||||
rv = CreateTemplateBuilder(aElement);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
TemplateBuilderHookup* hookup = new TemplateBuilderHookup(aElement);
|
||||
rv = AddForwardReference(hookup);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1784,40 +1743,6 @@ XULDocument::RemoveSubtreeFromDocument(nsIContent* aContent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULDocument::SetTemplateBuilderFor(nsIContent* aContent,
|
||||
nsIXULTemplateBuilder* aBuilder)
|
||||
{
|
||||
if (! mTemplateBuilderTable) {
|
||||
if (!aBuilder) {
|
||||
return NS_OK;
|
||||
}
|
||||
mTemplateBuilderTable = new BuilderTable;
|
||||
}
|
||||
|
||||
if (aBuilder) {
|
||||
mTemplateBuilderTable->Put(aContent, aBuilder);
|
||||
}
|
||||
else {
|
||||
mTemplateBuilderTable->Remove(aContent);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
XULDocument::GetTemplateBuilderFor(nsIContent* aContent,
|
||||
nsIXULTemplateBuilder** aResult)
|
||||
{
|
||||
if (mTemplateBuilderTable) {
|
||||
mTemplateBuilderTable->Get(aContent, aResult);
|
||||
}
|
||||
else
|
||||
*aResult = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
GetRefMapAttribute(Element* aElement, nsAutoString* aValue)
|
||||
{
|
||||
@ -3630,95 +3555,6 @@ XULDocument::AddAttributes(nsXULPrototypeElement* aPrototype,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
XULDocument::CheckTemplateBuilderHookup(Element* aElement,
|
||||
bool* aNeedsHookup)
|
||||
{
|
||||
// See if the element already has a `database' attribute. If it
|
||||
// does, then the template builder has already been created.
|
||||
//
|
||||
// XXX This approach will crash and burn (well, maybe not _that_
|
||||
// bad) if aElement is not a XUL element.
|
||||
//
|
||||
// XXXvarga Do we still want to support non XUL content?
|
||||
RefPtr<nsXULElement> xulElement = nsXULElement::FromContent(aElement);
|
||||
if (xulElement) {
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> ds = xulElement->GetDatabase();
|
||||
if (ds) {
|
||||
*aNeedsHookup = false;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Check aElement for a 'datasources' attribute, if it has
|
||||
// one a XUL template builder needs to be hooked up.
|
||||
*aNeedsHookup = aElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::datasources);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsresult
|
||||
XULDocument::CreateTemplateBuilder(Element* aElement)
|
||||
{
|
||||
// Check if need to construct a tree builder or content builder.
|
||||
bool isTreeBuilder = false;
|
||||
|
||||
// return successful if the element is not is a document, as an inline
|
||||
// script could have removed it
|
||||
nsIDocument* document = aElement->GetUncomposedDoc();
|
||||
NS_ENSURE_TRUE(document, NS_OK);
|
||||
|
||||
int32_t nameSpaceID;
|
||||
nsAtom* baseTag = document->BindingManager()->
|
||||
ResolveTag(aElement, &nameSpaceID);
|
||||
|
||||
if ((nameSpaceID == kNameSpaceID_XUL) && (baseTag == nsGkAtoms::tree)) {
|
||||
// By default, we build content for a tree and then we attach
|
||||
// the tree content view. However, if the `dont-build-content'
|
||||
// flag is set, then we we'll attach a tree builder which
|
||||
// directly implements the tree view.
|
||||
|
||||
nsAutoString flags;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::flags, flags);
|
||||
if (flags.Find(NS_LITERAL_STRING("dont-build-content")) >= 0) {
|
||||
isTreeBuilder = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isTreeBuilder) {
|
||||
// Create and initialize a tree builder.
|
||||
RefPtr<nsXULTreeBuilder> builder = new nsXULTreeBuilder(aElement);
|
||||
nsresult rv = builder->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Create a <treechildren> if one isn't there already.
|
||||
// XXXvarga what about attributes?
|
||||
RefPtr<Element> bodyContent;
|
||||
nsXULContentUtils::FindChildByTag(aElement, kNameSpaceID_XUL,
|
||||
nsGkAtoms::treechildren,
|
||||
getter_AddRefs(bodyContent));
|
||||
|
||||
if (!bodyContent) {
|
||||
bodyContent =
|
||||
document->CreateElem(nsDependentAtomString(nsGkAtoms::treechildren),
|
||||
nullptr, kNameSpaceID_XUL);
|
||||
|
||||
aElement->AppendChildTo(bodyContent, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Create and initialize a content builder.
|
||||
nsCOMPtr<nsIXULTemplateBuilder> builder;
|
||||
nsresult rv = NS_NewXULContentBuilder(aElement, getter_AddRefs(builder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
builder->CreateContents(aElement, false);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
XULDocument::AddPrototypeSheets()
|
||||
{
|
||||
@ -4034,30 +3870,6 @@ XULDocument::BroadcasterHookup::~BroadcasterHookup()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// XULDocument::TemplateBuilderHookup
|
||||
//
|
||||
|
||||
nsForwardReference::Result
|
||||
XULDocument::TemplateBuilderHookup::Resolve()
|
||||
{
|
||||
bool needsHookup;
|
||||
nsresult rv = CheckTemplateBuilderHookup(mElement, &needsHookup);
|
||||
if (NS_FAILED(rv))
|
||||
return eResolve_Error;
|
||||
|
||||
if (needsHookup) {
|
||||
rv = CreateTemplateBuilder(mElement);
|
||||
if (NS_FAILED(rv))
|
||||
return eResolve_Error;
|
||||
}
|
||||
|
||||
return eResolve_Succeeded;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
|
@ -130,10 +130,6 @@ public:
|
||||
|
||||
NS_IMETHOD AddSubtreeToDocument(nsIContent* aContent) override;
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aContent) override;
|
||||
NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent,
|
||||
nsIXULTemplateBuilder* aBuilder) override;
|
||||
NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent,
|
||||
nsIXULTemplateBuilder** aResult) override;
|
||||
NS_IMETHOD OnPrototypeLoadDone(bool aResumeWalk) override;
|
||||
bool OnDocumentParserError() override;
|
||||
|
||||
@ -352,12 +348,6 @@ protected:
|
||||
|
||||
nsCOMPtr<nsIDOMXULCommandDispatcher> mCommandDispatcher; // [OWNER] of the focus tracker
|
||||
|
||||
// Maintains the template builders that have been attached to
|
||||
// content elements
|
||||
typedef nsInterfaceHashtable<nsISupportsHashKey, nsIXULTemplateBuilder>
|
||||
BuilderTable;
|
||||
BuilderTable* mTemplateBuilderTable;
|
||||
|
||||
uint32_t mPendingSheets;
|
||||
|
||||
/**
|
||||
@ -468,18 +458,6 @@ protected:
|
||||
char16_t* mOffThreadCompileStringBuf;
|
||||
size_t mOffThreadCompileStringLength;
|
||||
|
||||
/**
|
||||
* Check if a XUL template builder has already been hooked up.
|
||||
*/
|
||||
static nsresult
|
||||
CheckTemplateBuilderHookup(mozilla::dom::Element* aElement, bool* aNeedsHookup);
|
||||
|
||||
/**
|
||||
* Create a XUL template builder on the specified node.
|
||||
*/
|
||||
static nsresult
|
||||
CreateTemplateBuilder(Element* aElement);
|
||||
|
||||
/**
|
||||
* Add the current prototype's style sheets (currently it's just
|
||||
* style overlays from the chrome registry) to the document.
|
||||
@ -567,21 +545,6 @@ protected:
|
||||
|
||||
friend class OverlayForwardReference;
|
||||
|
||||
class TemplateBuilderHookup : public nsForwardReference
|
||||
{
|
||||
protected:
|
||||
nsCOMPtr<Element> mElement; // [OWNER]
|
||||
|
||||
public:
|
||||
explicit TemplateBuilderHookup(Element* aElement)
|
||||
: mElement(aElement) {}
|
||||
|
||||
virtual Phase GetPhase() override { return eHookup; }
|
||||
virtual Result Resolve() override;
|
||||
};
|
||||
|
||||
friend class TemplateBuilderHookup;
|
||||
|
||||
// The out params of FindBroadcaster only have values that make sense when
|
||||
// the method returns NS_FINDBROADCASTER_FOUND. In all other cases, the
|
||||
// values of the out params should not be relied on (though *aListener and
|
||||
|
@ -12,8 +12,6 @@ MOCHITEST_MANIFESTS += ['test/mochitest.ini']
|
||||
MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
|
||||
|
||||
if CONFIG['MOZ_XUL']:
|
||||
DIRS += ['templates']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIXULOverlayProvider.idl',
|
||||
]
|
||||
@ -26,16 +24,19 @@ if CONFIG['MOZ_XUL']:
|
||||
UNIFIED_SOURCES += [
|
||||
'nsXULCommandDispatcher.cpp',
|
||||
'nsXULContentSink.cpp',
|
||||
'nsXULContentUtils.cpp',
|
||||
'nsXULElement.cpp',
|
||||
'nsXULPopupListener.cpp',
|
||||
'nsXULPrototypeCache.cpp',
|
||||
'nsXULPrototypeDocument.cpp',
|
||||
'nsXULSortService.cpp',
|
||||
'XULDocument.cpp',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIController.idl',
|
||||
'nsIControllers.idl',
|
||||
'nsIXULSortService.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'xul'
|
||||
@ -50,7 +51,6 @@ LOCAL_INCLUDES += [
|
||||
'/dom/html',
|
||||
'/dom/xbl',
|
||||
'/dom/xml',
|
||||
'/dom/xul/templates',
|
||||
'/layout/base',
|
||||
'/layout/generic',
|
||||
'/layout/style',
|
||||
|
@ -53,19 +53,6 @@ public:
|
||||
*/
|
||||
NS_IMETHOD RemoveSubtreeFromDocument(nsIContent* aElement) = 0;
|
||||
|
||||
/**
|
||||
* Attach a XUL template builder to the specified content node.
|
||||
* @param aBuilder the template builder to attach, or null if
|
||||
* the builder is to be removed.
|
||||
*/
|
||||
NS_IMETHOD SetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder* aBuilder) = 0;
|
||||
|
||||
/**
|
||||
* Retrieve the XUL template builder that's attached to a content
|
||||
* node.
|
||||
*/
|
||||
NS_IMETHOD GetTemplateBuilderFor(nsIContent* aContent, nsIXULTemplateBuilder** aResult) = 0;
|
||||
|
||||
/**
|
||||
* This is invoked whenever the prototype for this document is loaded
|
||||
* and should be walked, regardless of whether the XUL cache is
|
||||
|
158
dom/xul/nsXULContentUtils.cpp
Normal file
158
dom/xul/nsXULContentUtils.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
A package of routines shared by the XUL content code.
|
||||
|
||||
*/
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXULCommandDispatcher.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
nsIRDFService* nsXULContentUtils::gRDF;
|
||||
nsICollation *nsXULContentUtils::gCollation;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Constructors n' stuff
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::Init()
|
||||
{
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
nsresult rv = CallGetService(kRDFServiceCID, &gRDF);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::Finish()
|
||||
{
|
||||
NS_IF_RELEASE(gRDF);
|
||||
NS_IF_RELEASE(gCollation);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsICollation*
|
||||
nsXULContentUtils::GetCollation()
|
||||
{
|
||||
if (!gCollation) {
|
||||
nsCOMPtr<nsICollationFactory> colFactory =
|
||||
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
|
||||
if (colFactory) {
|
||||
DebugOnly<nsresult> rv = colFactory->CreateCollation(&gCollation);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"couldn't create collation instance");
|
||||
} else
|
||||
NS_ERROR("couldn't create instance of collation factory");
|
||||
}
|
||||
|
||||
return gCollation;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::FindChildByTag(nsIContent* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsAtom* aTag,
|
||||
Element** aResult)
|
||||
{
|
||||
for (nsIContent* child = aElement->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
|
||||
if (child->IsElement() &&
|
||||
child->NodeInfo()->Equals(aTag, aNameSpaceID)) {
|
||||
NS_ADDREF(*aResult = child->AsElement());
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
return NS_RDF_NO_VALUE; // not found
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, Element* aElement)
|
||||
{
|
||||
// Deal with setting up a 'commandupdater'. Pulls the 'events' and
|
||||
// 'targets' attributes off of aElement, and adds it to the
|
||||
// document's command dispatcher.
|
||||
NS_PRECONDITION(aDocument != nullptr, "null ptr");
|
||||
if (! aDocument)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aElement != nullptr, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(aDocument);
|
||||
NS_ASSERTION(xuldoc != nullptr, "not a xul document");
|
||||
if (! xuldoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher;
|
||||
rv = xuldoc->GetCommandDispatcher(getter_AddRefs(dispatcher));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get dispatcher");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(dispatcher != nullptr, "no dispatcher");
|
||||
if (! dispatcher)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsAutoString events;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events);
|
||||
if (events.IsEmpty())
|
||||
events.Assign('*');
|
||||
|
||||
nsAutoString targets;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::targets, targets);
|
||||
|
||||
if (targets.IsEmpty())
|
||||
targets.Assign('*');
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(aElement);
|
||||
NS_ASSERTION(domelement != nullptr, "not a DOM element");
|
||||
if (! domelement)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = dispatcher->AddCommandUpdater(domelement, events, targets);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
66
dom/xul/nsXULContentUtils.h
Normal file
66
dom/xul/nsXULContentUtils.h
Normal file
@ -0,0 +1,66 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
|
||||
A package of routines shared by the XUL content code.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsXULContentUtils_h__
|
||||
#define nsXULContentUtils_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsAtom;
|
||||
class nsICollation;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsIRDFService;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
|
||||
class nsXULContentUtils
|
||||
{
|
||||
protected:
|
||||
static nsIRDFService* gRDF;
|
||||
static nsICollation *gCollation;
|
||||
|
||||
static bool gDisableXULCache;
|
||||
|
||||
static int
|
||||
DisableXULCacheChangedCallback(const char* aPrefName, void* aClosure);
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
Init();
|
||||
|
||||
static nsresult
|
||||
Finish();
|
||||
|
||||
static nsresult
|
||||
FindChildByTag(nsIContent *aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsAtom* aTag,
|
||||
mozilla::dom::Element** aResult);
|
||||
|
||||
static nsresult
|
||||
SetCommandUpdater(nsIDocument* aDocument, mozilla::dom::Element* aElement);
|
||||
|
||||
static nsIRDFService*
|
||||
RDFService()
|
||||
{
|
||||
return gRDF;
|
||||
}
|
||||
|
||||
static nsICollation*
|
||||
GetCollation();
|
||||
};
|
||||
|
||||
#endif // nsXULContentUtils_h__
|
@ -33,9 +33,6 @@
|
||||
#include "nsIObjectOutputStream.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
@ -45,11 +42,9 @@
|
||||
#include "nsViewManager.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIXULDocument.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsContentCID.h"
|
||||
#include "mozilla/dom/Event.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULControllers.h"
|
||||
@ -70,11 +65,9 @@
|
||||
#include "nsJSPrincipals.h"
|
||||
#include "nsDOMAttributeMap.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "rdf.h"
|
||||
#include "nsIControllers.h"
|
||||
#include "nsAttrValueOrString.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
@ -332,11 +325,6 @@ nsXULElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
|
||||
aPreallocateChildren);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX TODO: set up RDF generic builder n' stuff if there is a
|
||||
// 'datasources' attribute? This is really kind of tricky,
|
||||
// because then we'd need to -selectively- copy children that
|
||||
// -weren't- generated from RDF. Ugh. Forget it.
|
||||
|
||||
// Note that we're _not_ copying mControllers.
|
||||
|
||||
uint32_t count = mAttrsAndChildren.AttrCount();
|
||||
@ -1336,54 +1324,6 @@ nsXULElement::PreHandleEvent(EventChainVisitor& aVisitor)
|
||||
return nsStyledElement::PreHandleEvent(aVisitor);
|
||||
}
|
||||
|
||||
// XXX This _should_ be an implementation method, _not_ publicly exposed :-(
|
||||
already_AddRefed<nsIRDFResource>
|
||||
nsXULElement::GetResource(ErrorResult& rv)
|
||||
{
|
||||
nsAutoString id;
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::ref, id);
|
||||
if (id.IsEmpty()) {
|
||||
GetAttr(kNameSpaceID_None, nsGkAtoms::id, id);
|
||||
}
|
||||
|
||||
if (id.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource;
|
||||
rv = nsXULContentUtils::RDFService()->
|
||||
GetUnicodeResource(id, getter_AddRefs(resource));
|
||||
return resource.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIRDFCompositeDataSource>
|
||||
nsXULElement::GetDatabase()
|
||||
{
|
||||
nsCOMPtr<nsIXULTemplateBuilder> builder = GetBuilder();
|
||||
if (!builder) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> database;
|
||||
builder->GetDatabase(getter_AddRefs(database));
|
||||
return database.forget();
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<nsIXULTemplateBuilder>
|
||||
nsXULElement::GetBuilder()
|
||||
{
|
||||
// XXX sXBL/XBL2 issue! Owner or current document?
|
||||
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(GetUncomposedDoc());
|
||||
if (!xuldoc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIXULTemplateBuilder> builder;
|
||||
xuldoc->GetTemplateBuilderFor(this, getter_AddRefs(builder));
|
||||
return builder.forget();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Implementation methods
|
||||
|
||||
|
@ -22,10 +22,7 @@
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXULElement.h"
|
||||
#include "nsIDOMXULMultSelectCntrlEl.h"
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsAttrAndChildArray.h"
|
||||
#include "nsGkAtoms.h"
|
||||
@ -333,12 +330,11 @@ public:
|
||||
|
||||
// XUL element specific bits
|
||||
enum {
|
||||
XUL_ELEMENT_TEMPLATE_GENERATED = XUL_ELEMENT_FLAG_BIT(0),
|
||||
XUL_ELEMENT_HAS_CONTENTMENU_LISTENER = XUL_ELEMENT_FLAG_BIT(1),
|
||||
XUL_ELEMENT_HAS_POPUP_LISTENER = XUL_ELEMENT_FLAG_BIT(2)
|
||||
XUL_ELEMENT_HAS_CONTENTMENU_LISTENER = XUL_ELEMENT_FLAG_BIT(0),
|
||||
XUL_ELEMENT_HAS_POPUP_LISTENER = XUL_ELEMENT_FLAG_BIT(1)
|
||||
};
|
||||
|
||||
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 3);
|
||||
ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET + 2);
|
||||
|
||||
#undef XUL_ELEMENT_FLAG_BIT
|
||||
|
||||
@ -397,15 +393,6 @@ public:
|
||||
int32_t aModType) const override;
|
||||
NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
|
||||
|
||||
// XUL element methods
|
||||
/**
|
||||
* The template-generated flag is used to indicate that a
|
||||
* template-generated element has already had its children generated.
|
||||
*/
|
||||
void SetTemplateGenerated() { SetFlags(XUL_ELEMENT_TEMPLATE_GENERATED); }
|
||||
void ClearTemplateGenerated() { UnsetFlags(XUL_ELEMENT_TEMPLATE_GENERATED); }
|
||||
bool GetTemplateGenerated() { return HasFlag(XUL_ELEMENT_TEMPLATE_GENERATED); }
|
||||
|
||||
// nsIDOMNode
|
||||
NS_FORWARD_NSIDOMNODE_TO_NSINODE
|
||||
// And since that shadowed GetParentElement with the XPCOM
|
||||
@ -636,14 +623,6 @@ public:
|
||||
{
|
||||
SetXULAttr(nsGkAtoms::top, aValue, rv);
|
||||
}
|
||||
void GetDatasources(DOMString& aValue) const
|
||||
{
|
||||
GetXULAttr(nsGkAtoms::datasources, aValue);
|
||||
}
|
||||
void SetDatasources(const nsAString& aValue, mozilla::ErrorResult& rv)
|
||||
{
|
||||
SetXULAttr(nsGkAtoms::datasources, aValue, rv);
|
||||
}
|
||||
void GetRef(DOMString& aValue) const
|
||||
{
|
||||
GetXULAttr(nsGkAtoms::ref, aValue);
|
||||
@ -684,9 +663,6 @@ public:
|
||||
{
|
||||
SetXULBoolAttr(nsGkAtoms::allowevents, aAllowEvents);
|
||||
}
|
||||
already_AddRefed<nsIRDFCompositeDataSource> GetDatabase();
|
||||
already_AddRefed<nsIXULTemplateBuilder> GetBuilder();
|
||||
already_AddRefed<nsIRDFResource> GetResource(mozilla::ErrorResult& rv);
|
||||
nsIControllers* GetControllers(mozilla::ErrorResult& rv);
|
||||
// Note: this can only fail if the do_CreateInstance for the boxobject
|
||||
// contact fails for some reason.
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsXULSortService.h"
|
||||
#include "nsXULElement.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
@ -93,23 +91,8 @@ XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
|
||||
nsSortState* aSortState,
|
||||
nsTArray<contentSortInfo>& aSortItems)
|
||||
{
|
||||
// if there is a template attached to the sort node, use the builder to get
|
||||
// the items to be sorted
|
||||
RefPtr<nsXULElement> element = nsXULElement::FromContent(aContainer);
|
||||
if (element) {
|
||||
nsCOMPtr<nsIXULTemplateBuilder> builder = element->GetBuilder();
|
||||
|
||||
if (builder) {
|
||||
nsresult rv = builder->GetQueryProcessor(getter_AddRefs(aSortState->processor));
|
||||
if (NS_FAILED(rv) || !aSortState->processor)
|
||||
return rv;
|
||||
|
||||
return GetTemplateItemsToSort(aContainer, builder, aSortState, aSortItems);
|
||||
}
|
||||
}
|
||||
|
||||
// if there is no template builder, just get the children. For trees,
|
||||
// get the treechildren element as use that as the parent
|
||||
// Get the children. For trees, get the treechildren element and
|
||||
// use that as the parent
|
||||
RefPtr<Element> treechildren;
|
||||
if (aContainer->NodeInfo()->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
|
||||
nsXULContentUtils::FindChildByTag(aContainer,
|
||||
@ -136,39 +119,6 @@ XULSortServiceImpl::GetItemsToSort(nsIContent *aContainer,
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
XULSortServiceImpl::GetTemplateItemsToSort(nsIContent* aContainer,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
nsSortState* aSortState,
|
||||
nsTArray<contentSortInfo>& aSortItems)
|
||||
{
|
||||
for (nsIContent* child = aContainer->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
|
||||
nsCOMPtr<nsIDOMElement> childnode = do_QueryInterface(child);
|
||||
|
||||
nsCOMPtr<nsIXULTemplateResult> result;
|
||||
nsresult rv = aBuilder->GetResultForContent(childnode, getter_AddRefs(result));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (result) {
|
||||
contentSortInfo* cinfo = aSortItems.AppendElement();
|
||||
if (!cinfo)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
cinfo->content = child;
|
||||
cinfo->result = result;
|
||||
}
|
||||
else if (!aContainer->IsXULElement(nsGkAtoms::_template)) {
|
||||
rv = GetTemplateItemsToSort(child, aBuilder, aSortState, aSortItems);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int
|
||||
testSortCallback(const void *data1, const void *data2, void *privateData)
|
||||
{
|
||||
@ -179,37 +129,21 @@ testSortCallback(const void *data1, const void *data2, void *privateData)
|
||||
|
||||
int32_t sortOrder = 0;
|
||||
|
||||
if (sortState->direction == nsSortState_natural && sortState->processor) {
|
||||
// sort in natural order
|
||||
sortState->processor->CompareResults(left->result, right->result,
|
||||
nullptr, sortState->sortHints, &sortOrder);
|
||||
}
|
||||
else {
|
||||
int32_t length = sortState->sortKeys.Length();
|
||||
for (int32_t t = 0; t < length; t++) {
|
||||
// for templates, use the query processor to do sorting
|
||||
if (sortState->processor) {
|
||||
sortState->processor->CompareResults(left->result, right->result,
|
||||
sortState->sortKeys[t],
|
||||
sortState->sortHints, &sortOrder);
|
||||
if (sortOrder)
|
||||
break;
|
||||
} else {
|
||||
// no template, so just compare attributes. Ignore namespaces for now.
|
||||
nsAutoString leftstr, rightstr;
|
||||
if (left->content->IsElement()) {
|
||||
left->content->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
sortState->sortKeys[t],
|
||||
leftstr);
|
||||
}
|
||||
if (right->content->IsElement()) {
|
||||
right->content->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
sortState->sortKeys[t], rightstr);
|
||||
}
|
||||
|
||||
sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
|
||||
}
|
||||
int32_t length = sortState->sortKeys.Length();
|
||||
for (int32_t t = 0; t < length; t++) {
|
||||
// compare attributes. Ignore namespaces for now.
|
||||
nsAutoString leftstr, rightstr;
|
||||
if (left->content->IsElement()) {
|
||||
left->content->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
sortState->sortKeys[t],
|
||||
leftstr);
|
||||
}
|
||||
if (right->content->IsElement()) {
|
||||
right->content->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
sortState->sortKeys[t], rightstr);
|
||||
}
|
||||
|
||||
sortOrder = XULSortServiceImpl::CompareValues(leftstr, rightstr, sortState->sortHints);
|
||||
}
|
||||
|
||||
if (sortState->direction == nsSortState_descending)
|
||||
@ -489,7 +423,6 @@ XULSortServiceImpl::Sort(nsIDOMNode* aNode,
|
||||
SetSortHints(sortNode, &sortState);
|
||||
rv = SortContainer(sortNode, &sortState);
|
||||
|
||||
sortState.processor = nullptr; // don't hang on to this reference
|
||||
return rv;
|
||||
}
|
||||
|
@ -4,18 +4,16 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
This sort service is used to sort template built content or content by attribute.
|
||||
This sort service is used to sort content by attribute.
|
||||
*/
|
||||
|
||||
#ifndef nsXULTemplateResultSetRDF_h
|
||||
#define nsXULTemplateResultSetRDF_h
|
||||
#ifndef nsXULSortService_h
|
||||
#define nsXULSortService_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
#include "nsIXULSortService.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
@ -32,7 +30,6 @@ struct nsSortState
|
||||
MOZ_INIT_OUTSIDE_CTOR bool invertSort;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool inbetweenSeparatorSort;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool sortStaticsLast;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool isContainerRDFSeq;
|
||||
|
||||
uint32_t sortHints;
|
||||
|
||||
@ -40,19 +37,16 @@ struct nsSortState
|
||||
nsAutoString sort;
|
||||
nsTArray<RefPtr<nsAtom>> sortKeys;
|
||||
|
||||
nsCOMPtr<nsIXULTemplateQueryProcessor> processor;
|
||||
nsCOMPtr<nsIContent> lastContainer;
|
||||
MOZ_INIT_OUTSIDE_CTOR bool lastWasFirst, lastWasLast;
|
||||
|
||||
nsSortState()
|
||||
: initialized(false),
|
||||
isContainerRDFSeq(false),
|
||||
sortHints(0)
|
||||
{
|
||||
}
|
||||
void Traverse(nsCycleCollectionTraversalCallback &cb) const
|
||||
{
|
||||
cb.NoteXPCOMChild(processor);
|
||||
cb.NoteXPCOMChild(lastContainer);
|
||||
}
|
||||
};
|
||||
@ -61,12 +55,10 @@ struct nsSortState
|
||||
struct contentSortInfo {
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIContent> parent;
|
||||
nsCOMPtr<nsIXULTemplateResult> result;
|
||||
void swap(contentSortInfo& other)
|
||||
{
|
||||
content.swap(other.content);
|
||||
parent.swap(other.parent);
|
||||
result.swap(other.result);
|
||||
}
|
||||
};
|
||||
|
||||
@ -122,15 +114,6 @@ public:
|
||||
nsSortState* aSortState,
|
||||
nsTArray<contentSortInfo>& aSortItems);
|
||||
|
||||
/**
|
||||
* Get the list of items to sort for template built content
|
||||
*/
|
||||
nsresult
|
||||
GetTemplateItemsToSort(nsIContent* aContainer,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
nsSortState* aSortState,
|
||||
nsTArray<contentSortInfo>& aSortItems);
|
||||
|
||||
/**
|
||||
* Sort a container using the supplied sort state details.
|
||||
*/
|
||||
@ -171,4 +154,4 @@ public:
|
||||
uint32_t aSortHints);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // nsXULSortService_h
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:m="urn:foo#">
|
||||
<rdf:Seq about="urn:x-rec:1">
|
||||
<rdf:li rdf:resource="urn:x-rec:2"/>
|
||||
</rdf:Seq>
|
||||
<rdf:Seq about="urn:x-rec:2">
|
||||
<rdf:li rdf:resource="urn:x-rec:3"/>
|
||||
</rdf:Seq>
|
||||
<rdf:Seq about="urn:x-rec:3">
|
||||
<rdf:li rdf:resource="urn:x-rec:1"/>
|
||||
</rdf:Seq>
|
||||
</rdf:RDF>
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
|
||||
<window id="child-iterate-recurse"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<vbox flex="1" style="overflow: auto;">
|
||||
|
||||
<vbox datasources="257752-1-recursion.rdf" ref="urn:x-rec:1">
|
||||
<template>
|
||||
<rule>
|
||||
<conditions>
|
||||
<content uri="?uri"/>
|
||||
<member container="?uri" child="?child"/>
|
||||
</conditions>
|
||||
<action>
|
||||
<vbox uri="?child" style="border: 1px solid grey; margin: 1em;">
|
||||
<label value="hi"/>
|
||||
</vbox>
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
</vbox>
|
||||
|
||||
</vbox>
|
||||
|
||||
</window>
|
@ -1,20 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script>
|
||||
|
||||
function rM(q1) { q1.parentNode.removeChild(q1); }
|
||||
|
||||
function init2()
|
||||
{
|
||||
rM(document.getElementById("t"));
|
||||
}
|
||||
|
||||
window.addEventListener("load", init2, false);
|
||||
|
||||
</script>
|
||||
|
||||
<foo id="t" datasources="1.rdf" />
|
||||
|
||||
</window>
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:s="urn:squarefree:a1:">
|
||||
<rdf:Description about="urn:root">
|
||||
<s:grapes>
|
||||
<rdf:Bag>
|
||||
<rdf:li>
|
||||
<rdf:Description/>
|
||||
</rdf:li>
|
||||
</rdf:Bag>
|
||||
</s:grapes>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<foo id="foo" datasources="330012-1.rdf" ref="urn:root">
|
||||
<template>
|
||||
<rule>
|
||||
<conditions>
|
||||
<content uri="?root"/>
|
||||
<triple subject="?root"
|
||||
predicate="urn:squarefree:a1:grapes"
|
||||
object="?lalala"/>
|
||||
<member container="?grapes" child="?grape"/>
|
||||
</conditions>
|
||||
<action>
|
||||
<bar uri="?grape"/>
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
</foo>
|
||||
|
||||
</window>
|
@ -1,7 +0,0 @@
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<box id="b">
|
||||
<box id="a" template="b"/>
|
||||
<triple/>
|
||||
</box>
|
||||
<box datasources="" observes="a" ref="bbb"/>
|
||||
</window>
|
@ -1,14 +0,0 @@
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<hbox datasources="nosuch.rdf" ref="urn:root">
|
||||
<template>
|
||||
<rule>
|
||||
<conditions>
|
||||
<triple subject="?a"/>
|
||||
</conditions>
|
||||
<action>
|
||||
<vbox uri="?b"/>
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
</hbox>
|
||||
</window>
|
@ -1 +0,0 @@
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" onload="document.getElementById('foo').removeAttribute('ref');"><foo id="foo" datasources="nosuch.rdf" ref="urn:root"><template/></foo></window>
|
@ -1 +0,0 @@
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"><hbox datasources="u"/></window>
|
@ -1,7 +0,0 @@
|
||||
load 257752-1-recursion.xul
|
||||
load 329884-1.xul
|
||||
skip-if(winWidget) load 330012-1.xul # bug 742455
|
||||
load 404346-1.xul
|
||||
load 415019-1.xul
|
||||
load 417840-1.xul
|
||||
load 424418-1.xul
|
@ -1,64 +0,0 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIXULBuilderListener.idl',
|
||||
'nsIXULSortService.idl',
|
||||
'nsIXULTemplateBuilder.idl',
|
||||
'nsIXULTemplateQueryProcessor.idl',
|
||||
'nsIXULTemplateResult.idl',
|
||||
'nsIXULTemplateRuleFilter.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'xultmpl'
|
||||
|
||||
EXPORTS += [
|
||||
'nsTreeRows.h',
|
||||
'nsXULTemplateBuilder.h',
|
||||
'nsXULTreeBuilder.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsContentSupportMap.cpp',
|
||||
'nsContentTestNode.cpp',
|
||||
'nsInstantiationNode.cpp',
|
||||
'nsRDFBinding.cpp',
|
||||
'nsRDFConInstanceTestNode.cpp',
|
||||
'nsRDFConMemberTestNode.cpp',
|
||||
'nsRDFPropertyTestNode.cpp',
|
||||
'nsRDFQuery.cpp',
|
||||
'nsResourceSet.cpp',
|
||||
'nsRuleNetwork.cpp',
|
||||
'nsTemplateMatch.cpp',
|
||||
'nsTemplateRule.cpp',
|
||||
'nsTreeRows.cpp',
|
||||
'nsXMLBinding.cpp',
|
||||
'nsXULContentBuilder.cpp',
|
||||
'nsXULContentUtils.cpp',
|
||||
'nsXULSortService.cpp',
|
||||
'nsXULTemplateBuilder.cpp',
|
||||
'nsXULTemplateQueryProcessorRDF.cpp',
|
||||
'nsXULTemplateQueryProcessorStorage.cpp',
|
||||
'nsXULTemplateQueryProcessorXML.cpp',
|
||||
'nsXULTemplateResultRDF.cpp',
|
||||
'nsXULTemplateResultSetRDF.cpp',
|
||||
'nsXULTemplateResultStorage.cpp',
|
||||
'nsXULTemplateResultXML.cpp',
|
||||
'nsXULTreeBuilder.cpp',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/dom/xul',
|
||||
'/layout/xul/tree/',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
|
||||
CXXFLAGS += ['-Wno-error=shadow']
|
@ -1,18 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsContentSupportMap.h"
|
||||
#include "nsXULElement.h"
|
||||
|
||||
void
|
||||
nsContentSupportMap::Remove(nsIContent* aElement)
|
||||
{
|
||||
nsIContent* child = aElement;
|
||||
do {
|
||||
mMap.Remove(child);
|
||||
child = child->GetNextNode(aElement);
|
||||
} while(child);
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsContentSupportMap_h__
|
||||
#define nsContentSupportMap_h__
|
||||
|
||||
#include "PLDHashTable.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
|
||||
/**
|
||||
* The nsContentSupportMap maintains a mapping from a "resource element"
|
||||
* in the content tree to the nsTemplateMatch that was used to instantiate it. This
|
||||
* is necessary to allow the XUL content to be built lazily. Specifically,
|
||||
* when building "resumes" on a partially-built content element, the builder
|
||||
* will walk upwards in the content tree to find the first element with an
|
||||
* 'id' attribute. This element is assumed to be the "resource element",
|
||||
* and allows the content builder to access the nsTemplateMatch (variable assignments
|
||||
* and rule information).
|
||||
*/
|
||||
class nsContentSupportMap {
|
||||
public:
|
||||
nsContentSupportMap() : mMap(PLDHashTable::StubOps(), sizeof(Entry)) { }
|
||||
~nsContentSupportMap() { }
|
||||
|
||||
nsresult Put(nsIContent* aElement, nsTemplateMatch* aMatch) {
|
||||
PLDHashEntryHdr* hdr = mMap.Add(aElement, mozilla::fallible);
|
||||
if (!hdr)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
Entry* entry = static_cast<Entry*>(hdr);
|
||||
NS_ASSERTION(entry->mMatch == nullptr, "over-writing entry");
|
||||
entry->mContent = aElement;
|
||||
entry->mMatch = aMatch;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool Get(nsIContent* aElement, nsTemplateMatch** aMatch) {
|
||||
PLDHashEntryHdr* hdr = mMap.Search(aElement);
|
||||
if (!hdr)
|
||||
return false;
|
||||
|
||||
Entry* entry = static_cast<Entry*>(hdr);
|
||||
*aMatch = entry->mMatch;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Remove(nsIContent* aElement);
|
||||
|
||||
void Clear() { mMap.Clear(); }
|
||||
|
||||
protected:
|
||||
PLDHashTable mMap;
|
||||
|
||||
struct Entry : public PLDHashEntryHdr {
|
||||
nsIContent* mContent;
|
||||
nsTemplateMatch* mMatch;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
@ -1,90 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsContentTestNode.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
using mozilla::LogLevel;
|
||||
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
nsContentTestNode::nsContentTestNode(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aRefVariable)
|
||||
: TestNode(nullptr),
|
||||
mProcessor(aProcessor),
|
||||
mDocument(nullptr),
|
||||
mRefVariable(aRefVariable),
|
||||
mTag(nullptr)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoString tag(NS_LITERAL_STRING("(none)"));
|
||||
if (mTag)
|
||||
mTag->ToString(tag);
|
||||
|
||||
nsAutoString refvar(NS_LITERAL_STRING("(none)"));
|
||||
if (aRefVariable)
|
||||
aRefVariable->ToString(refvar);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsContentTestNode[%p]: ref-var=%s tag=%s",
|
||||
this, NS_ConvertUTF16toUTF8(refvar).get(),
|
||||
NS_ConvertUTF16toUTF8(tag).get()));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const
|
||||
|
||||
{
|
||||
if (aCantHandleYet)
|
||||
*aCantHandleYet = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsContentTestNode::Constrain(InstantiationSet& aInstantiations)
|
||||
{
|
||||
// contrain the matches to those that have matched in the template builder
|
||||
|
||||
nsIXULTemplateBuilder* builder = mProcessor->GetBuilder();
|
||||
if (!builder) {
|
||||
aInstantiations.Clear();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
InstantiationSet::Iterator last = aInstantiations.Last();
|
||||
for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
|
||||
|
||||
nsCOMPtr<nsIRDFNode> refValue;
|
||||
bool hasRefBinding = inst->mAssignments.GetAssignmentFor(mRefVariable,
|
||||
getter_AddRefs(refValue));
|
||||
if (hasRefBinding) {
|
||||
nsCOMPtr<nsIRDFResource> refResource = do_QueryInterface(refValue);
|
||||
if (refResource) {
|
||||
bool generated;
|
||||
rv = builder->HasGeneratedContent(refResource, mTag, &generated);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (generated)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsContentTestNode_h__
|
||||
#define nsContentTestNode_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nscore.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorRDF;
|
||||
|
||||
/**
|
||||
* The nsContentTestNode is always the top node in a query's rule network. It
|
||||
* exists so that Constrain can filter out resources that aren't part of a
|
||||
* result.
|
||||
*/
|
||||
class nsContentTestNode : public TestNode
|
||||
{
|
||||
public:
|
||||
nsContentTestNode(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aContentVariable);
|
||||
|
||||
virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const override;
|
||||
|
||||
nsresult
|
||||
Constrain(InstantiationSet& aInstantiations) override;
|
||||
|
||||
void SetTag(nsAtom* aTag, nsIDOMDocument* aDocument)
|
||||
{
|
||||
mTag = aTag;
|
||||
mDocument = aDocument;
|
||||
}
|
||||
|
||||
protected:
|
||||
nsXULTemplateQueryProcessorRDF *mProcessor;
|
||||
nsIDOMDocument* mDocument;
|
||||
RefPtr<nsAtom> mRefVariable;
|
||||
RefPtr<nsAtom> mTag;
|
||||
};
|
||||
|
||||
#endif // nsContentTestNode_h__
|
||||
|
@ -1,28 +0,0 @@
|
||||
/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIXULTemplateBuilder;
|
||||
|
||||
// An nsIXULBuilderListener object is a listener that will be notified
|
||||
// when a template builder rebuilds its content.
|
||||
[scriptable, uuid(ac46be8f-c863-4c23-84a2-d0fcc8dfa9f4)]
|
||||
interface nsIXULBuilderListener: nsISupports {
|
||||
|
||||
/**
|
||||
* Called before a template builder rebuilds its content.
|
||||
* @param aBuilder the template builder that rebuilds the content.
|
||||
*/
|
||||
void willRebuild(in nsIXULTemplateBuilder aBuilder);
|
||||
|
||||
/**
|
||||
* Called after a template builder has rebuilt its content.
|
||||
* @param aBuilder the template builder that has rebuilt the content.
|
||||
*/
|
||||
void didRebuild(in nsIXULTemplateBuilder aBuilder);
|
||||
|
||||
};
|
@ -1,407 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsIContent;
|
||||
interface nsIXULBuilderListener;
|
||||
interface nsIXULTemplateResult;
|
||||
interface nsIXULTemplateRuleFilter;
|
||||
interface nsIXULTemplateQueryProcessor;
|
||||
interface nsIRDFResource;
|
||||
interface nsIRDFCompositeDataSource;
|
||||
interface nsIDOMDataTransfer;
|
||||
|
||||
%{C++
|
||||
class nsAtom;
|
||||
%}
|
||||
[ptr] native nsAtomPtr(nsAtom);
|
||||
[ptr] native Element (mozilla::dom::Element);
|
||||
|
||||
/**
|
||||
* A template builder, given an input source of data, a template, and a
|
||||
* reference point, generates a list of results from the input, and copies
|
||||
* part of the template for each result. Templates may generate content
|
||||
* recursively, using the same template, but with the previous iteration's
|
||||
* results as the reference point. As an example, for an XML datasource the
|
||||
* initial reference point would be a specific node in the DOM tree and a
|
||||
* template might generate a list of all child nodes. For the next iteration,
|
||||
* those children would be used to generate output for their child nodes and
|
||||
* so forth.
|
||||
*
|
||||
* A template builder is attached to a single DOM node; this node is called
|
||||
* the root node and is expected to contain a XUL template element as a direct
|
||||
* child. Different template builders may be specialized in the manner in
|
||||
* which they generate and display the resulting content from the template.
|
||||
*
|
||||
* The structure of a template is as follows:
|
||||
*
|
||||
* <rootnode datasources="" ref="">
|
||||
* <template>
|
||||
* <queryset>
|
||||
* <query>
|
||||
* </query>
|
||||
* <rule>
|
||||
* <conditions>...</conditions>
|
||||
* <bindings>...</bindings>
|
||||
* <action>...</action>
|
||||
* </rule>
|
||||
* </queryset>
|
||||
* </template>
|
||||
* </rootnode>
|
||||
*
|
||||
* The datasources attribute on the root node is used to identify the source
|
||||
* of data to be used. The ref attribute is used to specify the reference
|
||||
* point for the query. Currently, the datasource will either be an
|
||||
* nsIRDFDataSource or a DOM node. In the future, other datasource types may
|
||||
* be used.
|
||||
*
|
||||
* The <queryset> element contains a single query and one or more <rule>
|
||||
* elements. There may be more than one <queryset> if multiple queries are
|
||||
* desired, and this element is optional if only one query is needed -- in
|
||||
* that case the <query> and <rule>s are allowed to be children of the
|
||||
* <template> node
|
||||
*
|
||||
* The contents of the query are processed by a separate component called a
|
||||
* query processor. This query processor is expected to use this query to
|
||||
* generate results when asked by the template builder. The template builder
|
||||
* then generates output for each result based on the <rule> elements.
|
||||
*
|
||||
* This allows the query processor to be specific to a particular kind of
|
||||
* input data or query syntax, while the template builder remains independent
|
||||
* of the kind of data being used. Due to this, the query processor will be
|
||||
* supplied with the datasource and query which the template builder handles
|
||||
* in an opaque way, while the query processor handles these more
|
||||
* specifically.
|
||||
*
|
||||
* Results implement the nsIXULTemplateResult interface and may be identified
|
||||
* by an id which must be unique within a given set of query results.
|
||||
*
|
||||
* Each query may be accompanied by one or more <rule> elements. These rules
|
||||
* are evaluated by the template builder for each result produced by the
|
||||
* query. A rule consists of conditions that cause a rule to be either
|
||||
* accepted or rejected. The condition syntax allows for common conditional
|
||||
* handling; additional filtering may be applied by adding a custom filter
|
||||
* to a rule with the builder's addRuleFilter method.
|
||||
*
|
||||
* If a result passes a rule's conditions, this is considered a match, and the
|
||||
* content within the rule's <action> body is inserted as a sibling of the
|
||||
* <template>, assuming the template builder creates real DOM content. Only
|
||||
* one rule will match a result. For a tree builder, for example, the content
|
||||
* within the action body is used to create the tree rows instead. A matching
|
||||
* result must have its ruleMatched method called. When a result no longer
|
||||
* matches, the result's hasBeenRemoved method must be called.
|
||||
*
|
||||
* Optionally, the rule may have a <bindings> section which may be used to
|
||||
* define additional variables to be used within an action body. Each of these
|
||||
* declared bindings must be supplied to the query processor via its
|
||||
* addBinding method. The bindings are evaluated after a rule has matched.
|
||||
*
|
||||
* Templates may generate content recursively, using the previous iteration's
|
||||
* results as reference point to invoke the same queries. Since the reference
|
||||
* point is different, different output will typically be generated.
|
||||
*
|
||||
* The reference point nsIXULTemplateResult object for the first iteration is
|
||||
* determined by calling the query processor's translateRef method using the
|
||||
* value of the root node's ref attribute. This object may be retrieved later
|
||||
* via the builder's rootResult property.
|
||||
*
|
||||
* For convenience, each reference point as well as all results implement the
|
||||
* nsIXULTemplateResult interface, allowing the result objects from each
|
||||
* iteration to be used directly as the reference points for the next
|
||||
* iteration.
|
||||
*
|
||||
* When using multiple queries, each may generate results with the same id.
|
||||
* More than one of these results may match one of the rules in their
|
||||
* respective queries, however only the result for the earliest matching query
|
||||
* in the template becomes the active match and generates output. The
|
||||
* addResult, removeResult, replaceResult and resultBindingChanged methods may
|
||||
* be called by the query processor to indicate that the set of valid results
|
||||
* has changed, such that a different query may match. If a different match
|
||||
* would become active, the content for the existing match is removed and the
|
||||
* content for the new match is generated. A query processor is not required
|
||||
* to provide any support for updating results after they have been generated.
|
||||
*
|
||||
* See http://wiki.mozilla.org/XUL:Templates_Plan for details about templates.
|
||||
*/
|
||||
[scriptable, uuid(A583B676-5B02-4F9C-A0C9-CB850CB99818)]
|
||||
interface nsIXULTemplateBuilder : nsISupports
|
||||
{
|
||||
/**
|
||||
* The root node in the DOM to which this builder is attached.
|
||||
*/
|
||||
readonly attribute nsIDOMElement root;
|
||||
|
||||
/**
|
||||
* The opaque datasource object that is used for the template. This object
|
||||
* is created by the getDataSource method of the query processor. May be
|
||||
* null if the datasource has not been loaded yet. Set this attribute to
|
||||
* use a different datasource and rebuild the template.
|
||||
*
|
||||
* For an RDF datasource, this will be the same as the database. For XML
|
||||
* this will be the nsIDOMNode for the datasource document or node for
|
||||
* an inline reference (such as #name). Other query processors may use
|
||||
* other types for the datasource.
|
||||
*/
|
||||
attribute nsISupports datasource;
|
||||
|
||||
/**
|
||||
* The composite datasource that the template builder observes
|
||||
* and uses to create content. This is used only for RDF queries and is
|
||||
* maintained for backwards compatibility. It will be the same object as
|
||||
* the datasource property. For non-RDF queries, it will always be null.
|
||||
*/
|
||||
readonly attribute nsIRDFCompositeDataSource database;
|
||||
|
||||
/**
|
||||
* The virtual result representing the starting reference point,
|
||||
* determined by calling the query processor's translateRef method
|
||||
* with the root node's ref attribute as an argument.
|
||||
*/
|
||||
readonly attribute nsIXULTemplateResult rootResult;
|
||||
|
||||
/**
|
||||
* The query processor used to generate results.
|
||||
*/
|
||||
[noscript] readonly attribute nsIXULTemplateQueryProcessor queryProcessor;
|
||||
|
||||
/**
|
||||
* Force the template builder to rebuild its content. All existing content
|
||||
* will be removed first. The query processor's done() method will be
|
||||
* invoked during cleanup, followed by its initializeForBuilding method
|
||||
* when the content is to be regenerated.
|
||||
*
|
||||
*/
|
||||
void rebuild();
|
||||
|
||||
/**
|
||||
* Reload any of our RDF datasources that support nsIRDFRemoteDatasource.
|
||||
*
|
||||
* @note This is a temporary hack so that remote-XUL authors can
|
||||
* reload remote datasources. When RDF becomes remote-scriptable,
|
||||
* this will no longer be necessary.
|
||||
*/
|
||||
void refresh();
|
||||
|
||||
/**
|
||||
* Inform the template builder that a new result is available. The builder
|
||||
* will add this result to the set of results. The query node that the
|
||||
* new result applies to must be specified using the aQueryNode parameter.
|
||||
*
|
||||
* The builder will apply the rules associated with the query to the new
|
||||
* result, unless a result with the same id from an earlier query
|
||||
* supersedes it, and the result's RuleMatched method will be called if it
|
||||
* matches.
|
||||
*
|
||||
* @param aResult the result to add
|
||||
* @param aQueryNode the query that the result applies to
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aResult or aQueryNode are null
|
||||
*/
|
||||
void addResult(in nsIXULTemplateResult aResult, in nsIDOMNode aQueryNode);
|
||||
|
||||
/**
|
||||
* Inform the template builder that a result no longer applies. The builder
|
||||
* will call the remove content generated for the result, if any. If a different
|
||||
* query would then match instead, it will become the active match. This
|
||||
* method will have no effect if the result isn't known to the builder.
|
||||
*
|
||||
* @param aResult the result to remove
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aResult is null
|
||||
*/
|
||||
void removeResult(in nsIXULTemplateResult aResult);
|
||||
|
||||
/**
|
||||
* Inform the template builder that one result should be replaced with
|
||||
* another. Both the old result (aOldResult) and the new result
|
||||
* (aNewResult) must have the same id. The query node that the new result
|
||||
* applies to must be specified using the aQueryNode parameter.
|
||||
*
|
||||
* This method is expected to have the same effect as calling both
|
||||
* removeResult for the old result and addResult for the new result.
|
||||
*
|
||||
* @param aOldResult the old result
|
||||
* @param aNewResult the new result
|
||||
* @param aQueryNode the query that the new result applies to
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if either argument is null, or
|
||||
* NS_ERROR_INVALID_ARG if the ids don't match
|
||||
*/
|
||||
void replaceResult(in nsIXULTemplateResult aOldResult,
|
||||
in nsIXULTemplateResult aNewResult,
|
||||
in nsIDOMNode aQueryNode);
|
||||
|
||||
/**
|
||||
* Inform the template builder that one or more of the optional bindings
|
||||
* for a result has changed. In this case, the rules are not reapplied as
|
||||
* it is expected that the same rule will still apply. The builder will
|
||||
* resynchronize any variables that are referenced in the action body.
|
||||
*
|
||||
* @param aResult the result to change
|
||||
*
|
||||
* @throws NS_ERROR_NULL_POINTER if aResult is null
|
||||
*/
|
||||
void resultBindingChanged(in nsIXULTemplateResult aResult);
|
||||
|
||||
/**
|
||||
* Return the result for a given id. Only one such result is returned and
|
||||
* is always the result with that id associated with the active match.
|
||||
* This method will return null is there is no result for the id.
|
||||
*
|
||||
* @param aId the id to return the result for
|
||||
*/
|
||||
nsIXULTemplateResult getResultForId(in AString aId);
|
||||
|
||||
/**
|
||||
* Retrieve the result corresponding to a generated element, or null is
|
||||
* there isn't one.
|
||||
*
|
||||
* @param aContent element to result the result of
|
||||
*/
|
||||
nsIXULTemplateResult getResultForContent(in nsIDOMElement aElement);
|
||||
|
||||
/**
|
||||
* Returns true if the node has content generated for it. This method is
|
||||
* intended to be called only by the RDF query processor. If aTag is set,
|
||||
* the content must have a tag name that matches aTag. aTag may be ignored
|
||||
* for builders that don't generate real DOM content.
|
||||
*
|
||||
* @param aNode node to check
|
||||
* @param aTag tag that must match
|
||||
*/
|
||||
[noscript] boolean hasGeneratedContent(in nsIRDFResource aNode,
|
||||
in nsAtomPtr aTag);
|
||||
|
||||
/**
|
||||
* Adds a rule filter for a given rule, which may be used for specialized
|
||||
* rule filtering. Any existing filter on the rule is removed. The default
|
||||
* conditions specified inside the <rule> tag are applied before the
|
||||
* rule filter is applied, meaning that the filter may be used to further
|
||||
* filter out results but not reaccept results that have already been
|
||||
* rejected.
|
||||
*
|
||||
* @param aRule the rule to apply the filter to
|
||||
* @param aFilter the filter to add
|
||||
*/
|
||||
void addRuleFilter(in nsIDOMNode aRule, in nsIXULTemplateRuleFilter aFilter);
|
||||
|
||||
/**
|
||||
* Invoked lazily by a XUL element that needs its child content built.
|
||||
* If aForceCreation is true, then the contents of an element will be
|
||||
* generated even if it is closed. If false, the element will only
|
||||
* generate its contents if it is open. This behaviour is used with menus.
|
||||
*/
|
||||
[noscript] void createContents(in Element aElement,
|
||||
in boolean aForceCreation);
|
||||
|
||||
/**
|
||||
* Add a listener to this template builder. The template builder
|
||||
* holds a strong reference to the listener.
|
||||
*/
|
||||
void addListener(in nsIXULBuilderListener aListener);
|
||||
|
||||
/**
|
||||
* Remove a listener from this template builder.
|
||||
*/
|
||||
void removeListener(in nsIXULBuilderListener aListener);
|
||||
};
|
||||
|
||||
/**
|
||||
* nsIXULTreeBuilderObserver
|
||||
* This interface allows clients of the XULTreeBuilder to define domain
|
||||
* specific handling of specific nsITreeView methods that
|
||||
* XULTreeBuilder does not implement.
|
||||
*/
|
||||
[scriptable, uuid(57CED9A7-EC0B-4A0E-8AEB-5DA32EBE951C)]
|
||||
interface nsIXULTreeBuilderObserver : nsISupports
|
||||
{
|
||||
const long DROP_BEFORE = -1;
|
||||
const long DROP_ON = 0;
|
||||
const long DROP_AFTER = 1;
|
||||
/**
|
||||
* Methods used by the drag feedback code to determine if a drag is allowable at
|
||||
* the current location. To get the behavior where drops are only allowed on
|
||||
* items, such as the mailNews folder pane, always return false whe
|
||||
* the orientation is not DROP_ON.
|
||||
*/
|
||||
boolean canDrop(in long index, in long orientation, in nsIDOMDataTransfer dataTransfer);
|
||||
|
||||
/**
|
||||
* Called when the user drops something on this view. The |orientation| param
|
||||
* specifies before/on/after the given |row|.
|
||||
*/
|
||||
void onDrop(in long row, in long orientation, in nsIDOMDataTransfer dataTransfer);
|
||||
|
||||
/**
|
||||
* Called when an item is opened or closed.
|
||||
*/
|
||||
void onToggleOpenState (in long index);
|
||||
|
||||
/**
|
||||
* Called when a header is clicked.
|
||||
*/
|
||||
void onCycleHeader(in wstring colID, in nsIDOMElement elt);
|
||||
|
||||
/**
|
||||
* Called when a cell in a non-selectable cycling column (e.g.
|
||||
* unread/flag/etc.) is clicked.
|
||||
*/
|
||||
void onCycleCell(in long row, in wstring colID);
|
||||
|
||||
/**
|
||||
* Called when selection in the tree changes
|
||||
*/
|
||||
void onSelectionChanged();
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on the selection.
|
||||
* The tree will automatically invoke this method when certain keys
|
||||
* are pressed. For example, when the DEL key is pressed, performAction
|
||||
* will be called with the "delete" string.
|
||||
*/
|
||||
void onPerformAction(in wstring action);
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on a specific row.
|
||||
*/
|
||||
void onPerformActionOnRow(in wstring action, in long row);
|
||||
|
||||
/**
|
||||
* A command API that can be used to invoke commands on a specific cell.
|
||||
*/
|
||||
void onPerformActionOnCell(in wstring action, in long row, in wstring colID);
|
||||
};
|
||||
|
||||
[scriptable, uuid(06b31b15-ebf5-4e74-a0e2-6bc0a18a3969)]
|
||||
interface nsIXULTreeBuilder : nsISupports
|
||||
{
|
||||
/**
|
||||
* Retrieve the RDF resource associated with the specified row.
|
||||
*/
|
||||
nsIRDFResource getResourceAtIndex(in long aRowIndex);
|
||||
|
||||
/**
|
||||
* Retrieve the index associated with specified RDF resource.
|
||||
*/
|
||||
long getIndexOfResource(in nsIRDFResource resource);
|
||||
|
||||
/**
|
||||
* Add a Tree Builder Observer to handle Tree View
|
||||
* methods that the base builder does not implement.
|
||||
*/
|
||||
void addObserver(in nsIXULTreeBuilderObserver aObserver);
|
||||
|
||||
/**
|
||||
* Remove an Tree Builder Observer.
|
||||
*/
|
||||
void removeObserver(in nsIXULTreeBuilderObserver aObserver);
|
||||
|
||||
/**
|
||||
* Sort the contents of the tree using the specified column.
|
||||
*/
|
||||
void sort(in nsIDOMElement aColumnElement);
|
||||
};
|
||||
|
@ -1,280 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsIArray;
|
||||
interface nsISimpleEnumerator;
|
||||
interface nsIXULTemplateResult;
|
||||
interface nsIXULTemplateRuleFilter;
|
||||
interface nsIXULTemplateBuilder;
|
||||
|
||||
%{C++
|
||||
class nsAtom;
|
||||
%}
|
||||
[ptr] native nsAtomPtr(nsAtom);
|
||||
|
||||
/**
|
||||
* A query processor takes a template query and generates results for it given
|
||||
* a datasource and a reference point. There is a one-to-one relationship
|
||||
* between a template builder and a query processor. The template builder
|
||||
* creates the query processor, and there is no other means to retrieve it.
|
||||
*
|
||||
* A template query is the contents inside a <query> element within the
|
||||
* template. The actual syntax is opaque to the template builder and defined
|
||||
* by a query processor. The query is expected to consist of either text or
|
||||
* DOM nodes that, when executed by a call to the generateResults method, will
|
||||
* allow the generation of a list of results.
|
||||
*
|
||||
* The template builder will supply two variables, the reference variable and
|
||||
* the member variable to further indicate what part of the datasource is to
|
||||
* be examined in addition to the query itself. The reference is always
|
||||
* a placeholder for the starting point and the member is always a placeholder
|
||||
* for the end points (the results).
|
||||
*
|
||||
* The reference point is important when generating output recursively, as
|
||||
* the query will be the same for each iteration, however, the reference point
|
||||
* will differ.
|
||||
*
|
||||
* For instance, when examining an XML source, an XML query processor might
|
||||
* begin at the node referred by the reference variable and end at a list of
|
||||
* that node's children.
|
||||
*
|
||||
* Some queries may not need the reference variable if the syntax or the form
|
||||
* of the data implies the value. For instance, a datasource that holds a
|
||||
* table that can only produce one set of results.
|
||||
*
|
||||
* The reference variable may be specified in a template by setting the
|
||||
* "container" attribute on the <template> element to the variable to use. The
|
||||
* member variable may be specified in a similar way using the "member"
|
||||
* attribute, or it may be specified in the first <action> body in the
|
||||
* template as the value of a uri attribute on an element. A breadth-first
|
||||
* search of the first action is performed to find this element.
|
||||
*
|
||||
* If unspecified, the default value of the reference variable is ?uri.
|
||||
*
|
||||
* For example, a query might have the following syntax:
|
||||
*
|
||||
* (?id, ?name, ?url) from Bookmarks where parentfolder = ?start
|
||||
*
|
||||
* This query might generate a result for each bookmark within a given folder.
|
||||
* The variable ?start would be the reference variable, while the variable ?id
|
||||
* would be the member variable, since it is the unique value that identifies
|
||||
* a result. Each result will have the four variables referred to defined for
|
||||
* it and the values may be retrieved using the result's getBindingFor and
|
||||
* getBindingObjectFor methods.
|
||||
*
|
||||
* The template builder must call initializeForBuilding before the other
|
||||
* methods, except for translateRef. The builder will then call compileQuery
|
||||
* for each query in the template to compile the queries. When results need
|
||||
* to be generated, the builder will call generateResults. The
|
||||
* initializeForBuilding, compileQuery and addBinding methods may not be
|
||||
* called after generateResults has been called until the builder indicates
|
||||
* that the generated output is being removed by calling the done method.
|
||||
*
|
||||
* Currently, the datasource supplied to the methods will always be an
|
||||
* nsIRDFDataSource or a DOM node, and will always be the same one in between
|
||||
* calls to initializeForBuilding and done.
|
||||
*/
|
||||
[scriptable, uuid(C257573F-444F-468A-BA27-DE979DC55FE4)]
|
||||
interface nsIXULTemplateQueryProcessor : nsISupports
|
||||
{
|
||||
/**
|
||||
* Retrieve the datasource to use for the query processor. The list of
|
||||
* datasources in a template is specified using the datasources attribute as
|
||||
* a space separated list of URIs. This list is processed by the builder and
|
||||
* supplied to the query processor in the aDataSources array as a list of
|
||||
* nsIURI objects or nsIDOMNode objects. This method may return an object
|
||||
* corresponding to these URIs and the builder will supply this object to
|
||||
* other query processor methods. For example, for an XML source, the
|
||||
* datasource might be an nsIDOMNode.
|
||||
*
|
||||
* All of these URIs are checked by the builder so it is safe to use them,
|
||||
* however note that a URI that redirects may still needs to be checked to
|
||||
* ensure that the document containing aRootNode may access it. This is the
|
||||
* responsibility of the query processor if it needs to load the content of
|
||||
* the URI.
|
||||
*
|
||||
* If the query processor needs to load the datasource asynchronously, it
|
||||
* may set the aShouldDelayBuilding returned parameter to true to delay
|
||||
* building the template content, and call the builder's Rebuild method when
|
||||
* the data is available.
|
||||
*
|
||||
* @param aDataSources the list of nsIURI objects and/or nsIDOMNode objects
|
||||
* @param aRootNode the root node the builder is attached to
|
||||
* @param aIsTrusted true if the template is in a trusted document
|
||||
* @param aBuilder the template builder
|
||||
* @param aShouldDelayBuilding [out] whether the builder should wait to
|
||||
* build the content or not
|
||||
* @returns a datasource object
|
||||
*/
|
||||
nsISupports getDatasource(in nsIArray aDataSources,
|
||||
in nsIDOMNode aRootNode,
|
||||
in boolean aIsTrusted,
|
||||
in nsIXULTemplateBuilder aBuilder,
|
||||
out boolean aShouldDelayBuilding);
|
||||
|
||||
/**
|
||||
* Initialize for query generation. This will be called before the rules are
|
||||
* processed and whenever the template is rebuilt. This method must be
|
||||
* called once before any of the other query processor methods except for
|
||||
* translateRef.
|
||||
*
|
||||
* @param aDatasource datasource for the data
|
||||
* @param aBuilder the template builder
|
||||
* @param aRootNode the root node the builder is attached to
|
||||
*
|
||||
* @throws NS_ERROR_INVALID_ARG if the datasource is not supported or
|
||||
* NS_ERROR_UNEXPECTED if generateResults has already been called.
|
||||
*/
|
||||
void initializeForBuilding(in nsISupports aDatasource,
|
||||
in nsIXULTemplateBuilder aBuilder,
|
||||
in nsIDOMNode aRootNode);
|
||||
|
||||
/**
|
||||
* Called when the template builder is being destroyed so that the query
|
||||
* processor can clean up any state. The query processor should remove as
|
||||
* much state as possible, such as results or references to the builder.
|
||||
* This method will also be called when the template is going to be rebuilt.
|
||||
*/
|
||||
void done();
|
||||
|
||||
/**
|
||||
* Compile a query from a node. The result of this function will later be
|
||||
* passed to generateResults for result generation. If null is returned,
|
||||
* the query will be ignored.
|
||||
*
|
||||
* The template builder will call this method once for each query within
|
||||
* the template, before any results can be generated using generateResults,
|
||||
* but after initializeForBuilding has been called. This method should not
|
||||
* be called again for the same query unless the template is rebuilt.
|
||||
*
|
||||
* The reference variable may be used by the query processor as a
|
||||
* placeholder for the reference point, or starting point in the query.
|
||||
*
|
||||
* The member variable is determined from the member attribute on the
|
||||
* template, or from the uri in the first action's rule if that attribute is
|
||||
* not present. A rule processor may use the member variable as a hint to
|
||||
* indicate what variable is expected to contain the results.
|
||||
*
|
||||
* @param aBuilder the template builder
|
||||
* @param aQuery <query> node to compile
|
||||
* @param aRefVariable the reference variable
|
||||
* @param aMemberVariable the member variable
|
||||
*
|
||||
* @returns a compiled query object
|
||||
*/
|
||||
[noscript] nsISupports compileQuery(in nsIXULTemplateBuilder aBuilder,
|
||||
in nsIDOMNode aQuery,
|
||||
in nsAtomPtr aRefVariable,
|
||||
in nsAtomPtr aMemberVariable);
|
||||
|
||||
/**
|
||||
* Generate the results of a query and return them in an enumerator. The
|
||||
* enumerator must contain nsIXULTemplateResult objects. If there are no
|
||||
* results, an empty enumerator must be returned.
|
||||
*
|
||||
* The datasource will be the same as the one passed to the earlier
|
||||
* initializeForBuilding method. The context reference (aRef) is a reference
|
||||
* point used when calculating results.
|
||||
*
|
||||
* The value of aQuery must be the result of a previous call to compileQuery
|
||||
* from this query processor. This method may be called multiple times,
|
||||
* typically with different values for aRef.
|
||||
*
|
||||
* @param aDatasource datasource for the data
|
||||
* @param aRef context reference value used as a starting point
|
||||
* @param aQuery the compiled query returned from query compilation
|
||||
*
|
||||
* @returns an enumerator of nsIXULTemplateResult objects as the results
|
||||
*
|
||||
* @throws NS_ERROR_INVALID_ARG if aQuery is invalid
|
||||
*/
|
||||
nsISimpleEnumerator generateResults(in nsISupports aDatasource,
|
||||
in nsIXULTemplateResult aRef,
|
||||
in nsISupports aQuery);
|
||||
|
||||
/**
|
||||
* Add a variable binding for a particular rule. A binding allows an
|
||||
* additional variable to be set for a result, outside of those defined
|
||||
* within the query. These bindings are always optional, in that they will
|
||||
* never affect the results generated.
|
||||
*
|
||||
* This function will never be called after generateResults. Any bindings
|
||||
* that were added should be applied to each result when the result's
|
||||
* ruleMatched method is called, since the bindings are different for each
|
||||
* rule.
|
||||
*
|
||||
* The reference aRef may be used to determine the reference when
|
||||
* calculating the value for the binding, for example when a value should
|
||||
* depend on the value of another variable.
|
||||
*
|
||||
* The syntax of the expression aExpr is defined by the query processor. If
|
||||
* the syntax is invalid, the binding should be ignored. Only fatal errors
|
||||
* should be thrown, or NS_ERROR_UNEXPECTED if generateResults has already
|
||||
* been called.
|
||||
*
|
||||
* As an example, if the reference aRef is the variable '?count' which
|
||||
* holds the value 5, and the expression aExpr is the string '+2', the value
|
||||
* of the variable aVar would be 7, assuming the query processor considers
|
||||
* the syntax '+2' to mean add two to the reference.
|
||||
*
|
||||
* @param aRuleNode rule to add the binding to
|
||||
* @param aVar variable that will be bound
|
||||
* @param aRef variable that holds reference value
|
||||
* @param aExpr expression used to compute the value to assign
|
||||
*/
|
||||
[noscript] void addBinding(in nsIDOMNode aRuleNode,
|
||||
in nsAtomPtr aVar,
|
||||
in nsAtomPtr aRef,
|
||||
in AString aExpr);
|
||||
|
||||
/**
|
||||
* Translate a ref attribute string into a result. This is used as the
|
||||
* reference point by the template builder when generating the first level
|
||||
* of content. For recursive generation, the result from the parent
|
||||
* generation phase will be used directly as the reference so a translation
|
||||
* is not needed. This allows all levels to be generated using objects that
|
||||
* all implement the nsIXULTemplateResult interface.
|
||||
*
|
||||
* This method may be called before initializeForBuilding, so the
|
||||
* implementation may use the supplied datasource if it is needed to
|
||||
* translate the reference.
|
||||
*
|
||||
* @param aDatasource datasource for the data
|
||||
* @param aRefString the ref attribute string
|
||||
*
|
||||
* @return the translated ref
|
||||
*/
|
||||
nsIXULTemplateResult translateRef(in nsISupports aDatasource,
|
||||
in AString aRefString);
|
||||
|
||||
/**
|
||||
* Compare two results to determine their order, used when sorting results.
|
||||
* This method should return -1 when the left result is less than the right,
|
||||
* 0 if both are equivalent, and 1 if the left is greater than the right.
|
||||
* The comparison should only consider the values for the specified
|
||||
* variable.
|
||||
*
|
||||
* If the comparison variable is null, the results may be
|
||||
* sorted in a natural order, for instance, based on the order the data in
|
||||
* stored in the datasource.
|
||||
*
|
||||
* The sort hints are the flags in nsIXULSortService.
|
||||
*
|
||||
* This method must only be called with results that were created by this
|
||||
* query processor.
|
||||
*
|
||||
* @param aLeft the left result to compare
|
||||
* @param aRight the right result to compare
|
||||
* @param aVar variable to compare
|
||||
*
|
||||
* @param returns -1 if less, 0 if equal, or 1 if greater
|
||||
*/
|
||||
[noscript] int32_t compareResults(in nsIXULTemplateResult aLeft,
|
||||
in nsIXULTemplateResult aRight,
|
||||
in nsAtomPtr aVar,
|
||||
in unsigned long aSortHints);
|
||||
};
|
@ -1,120 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsIDOMNode;
|
||||
interface nsIRDFResource;
|
||||
|
||||
%{C++
|
||||
class nsAtom;
|
||||
%}
|
||||
[ptr] native nsAtomPtr(nsAtom);
|
||||
|
||||
/**
|
||||
* A single result generated from a template query. Each result is identified
|
||||
* by an id, which must be unique within the set of results produced from a
|
||||
* query. The result may optionally be identified by an RDF resource.
|
||||
*
|
||||
* Generally, the result and its id will be able to uniquely identify a node
|
||||
* in the source data, such as an RDF or XML node. In other contexts, such as
|
||||
* a database query, a result would represent a particular record.
|
||||
*
|
||||
* A result is expected to only be created by a query processor.
|
||||
*
|
||||
* Each result also contains a set of variable bindings. The value for a
|
||||
* particular variable may be retrieved using the getBindingFor and
|
||||
* getBindingObjectFor methods.
|
||||
*/
|
||||
[scriptable, uuid(ebea0230-36fa-41b7-8e31-760806057965)]
|
||||
interface nsIXULTemplateResult : nsISupports
|
||||
{
|
||||
/**
|
||||
* True if the result represents a container.
|
||||
*/
|
||||
readonly attribute boolean isContainer;
|
||||
|
||||
/**
|
||||
* True if the result represents an empty container.
|
||||
*/
|
||||
readonly attribute boolean isEmpty;
|
||||
|
||||
/**
|
||||
* True if the template builder may use this result as the reference point
|
||||
* for additional recursive processing of the template. The template builder
|
||||
* will reprocess the template using this result as the reference point and
|
||||
* generate output content that is expected to be inserted as children of the
|
||||
* output generated for this result. If false, child content is not
|
||||
* processed. This property identifies only the default handling and may be
|
||||
* overriden by syntax used in the template.
|
||||
*/
|
||||
readonly attribute boolean mayProcessChildren;
|
||||
|
||||
/**
|
||||
* ID of the result. The DOM element created for this result, if any, will
|
||||
* have its id attribute set to this value. The id must be unique for a
|
||||
* query.
|
||||
*/
|
||||
readonly attribute AString id;
|
||||
|
||||
/**
|
||||
* Resource for the result, which may be null. If set, the resource uri
|
||||
* must be the same as the ID property.
|
||||
*/
|
||||
readonly attribute nsIRDFResource resource;
|
||||
|
||||
/**
|
||||
* The type of the object. The predefined value 'separator' may be used
|
||||
* for separators. Other values may be used for application specific
|
||||
* purposes.
|
||||
*/
|
||||
readonly attribute AString type;
|
||||
|
||||
/**
|
||||
* Get the string representation of the value of a variable for this
|
||||
* result. This string will be used in the action body from a template as
|
||||
* the replacement text. For instance, if the text ?name appears in an
|
||||
* attribute within the action body, it will be replaced with the result
|
||||
* of this method. The question mark is considered part of the variable
|
||||
* name, thus aVar should be ?name and not simply name.
|
||||
*
|
||||
* @param aVar the variable to look up
|
||||
*
|
||||
* @return the value for the variable or a null string if it has no value
|
||||
*/
|
||||
[noscript] AString getBindingFor(in nsAtomPtr aVar);
|
||||
|
||||
/**
|
||||
* Get an object value for a variable such as ?name for this result.
|
||||
*
|
||||
* This method may return null for a variable, even if getBindingFor returns
|
||||
* a non-null value for the same variable. This method is provided as a
|
||||
* convenience when sorting results.
|
||||
*
|
||||
* @param aVar the variable to look up
|
||||
*
|
||||
* @return the value for the variable or null if it has no value
|
||||
*/
|
||||
[noscript] nsISupports getBindingObjectFor(in nsAtomPtr aVar);
|
||||
|
||||
/**
|
||||
* Indicate that a particular rule of a query has matched and that output
|
||||
* will be generated for it. Both the query as compiled by the query
|
||||
* processor's compileQuery method and the XUL <rule> element are supplied.
|
||||
* The query must always be one that was compiled by the query processor
|
||||
* that created this result. The <rule> element must always be a child of
|
||||
* the <query> element that was used to compile the query.
|
||||
*
|
||||
* @param aQuery the query that matched
|
||||
* @param aRuleNode the rule node that matched
|
||||
*/
|
||||
void ruleMatched(in nsISupports aQuery, in nsIDOMNode aRuleNode);
|
||||
|
||||
/**
|
||||
* Indicate that the output for a result has beeen removed and that the
|
||||
* result is no longer being used by the builder.
|
||||
*/
|
||||
void hasBeenRemoved();
|
||||
};
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsISupports;
|
||||
interface nsIXULTemplateResult;
|
||||
|
||||
/**
|
||||
* A rule filter may be used to add additional filtering of results to a rule.
|
||||
* The filter is used to further reject results from matching the template's
|
||||
* rules, beyond what the template syntax can do itself, thus allowing for
|
||||
* more complex result filtering. The rule filter is applied after the rule
|
||||
* syntax within the template.
|
||||
*
|
||||
* Only one filter may apply to each rule within the template and may be
|
||||
* assigned using the template builder's addRuleFilter method.
|
||||
*/
|
||||
[scriptable, uuid(819cd1ed-8010-42e1-a8b9-778b726a1ff3)]
|
||||
interface nsIXULTemplateRuleFilter : nsISupports
|
||||
{
|
||||
/**
|
||||
* Evaluate a result and return true if the result is accepted by this
|
||||
* filter, or false if it is rejected. Accepted results will have output
|
||||
* generated for them for the rule. Rejected results will not, but they
|
||||
* may still match another rule.
|
||||
*
|
||||
* @param aRef the result to examine
|
||||
* @param aRule the rule node
|
||||
*
|
||||
* @return true if the rule matches
|
||||
*/
|
||||
boolean match(in nsIXULTemplateResult aRef, in nsIDOMNode aRule);
|
||||
};
|
@ -1,83 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsInstantiationNode.h"
|
||||
#include "nsTemplateRule.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
nsInstantiationNode::nsInstantiationNode(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsRDFQuery* aQuery)
|
||||
: mProcessor(aProcessor),
|
||||
mQuery(aQuery)
|
||||
{
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsInstantiationNode[%p] query=%p", this, aQuery));
|
||||
|
||||
MOZ_COUNT_CTOR(nsInstantiationNode);
|
||||
}
|
||||
|
||||
|
||||
nsInstantiationNode::~nsInstantiationNode()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsInstantiationNode);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsInstantiationNode::Propagate(InstantiationSet& aInstantiations,
|
||||
bool aIsUpdate, bool& aTakenInstantiations)
|
||||
{
|
||||
// In update mode, iterate through the results and call the template
|
||||
// builder to update them. In non-update mode, cache them in the processor
|
||||
// to be used during processing. The results are cached in the processor
|
||||
// so that the simple rules are only computed once. In this situation, all
|
||||
// data for all queries are calculated at once.
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
aTakenInstantiations = false;
|
||||
|
||||
if (aIsUpdate) {
|
||||
// Iterate through newly added keys to determine which rules fired.
|
||||
//
|
||||
// XXXwaterson Unfortunately, this could also lead to retractions;
|
||||
// e.g., (container ?a ^empty false) could become "unmatched". How
|
||||
// to track those?
|
||||
nsCOMPtr<nsIDOMNode> querynode;
|
||||
mQuery->GetQueryNode(getter_AddRefs(querynode));
|
||||
|
||||
InstantiationSet::ConstIterator last = aInstantiations.Last();
|
||||
for (InstantiationSet::ConstIterator inst = aInstantiations.First(); inst != last; ++inst) {
|
||||
nsAssignmentSet assignments = inst->mAssignments;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> node;
|
||||
assignments.GetAssignmentFor(mQuery->mMemberVariable,
|
||||
getter_AddRefs(node));
|
||||
if (node) {
|
||||
nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(node);
|
||||
if (resource) {
|
||||
RefPtr<nsXULTemplateResultRDF> nextresult =
|
||||
new nsXULTemplateResultRDF(mQuery, *inst, resource);
|
||||
if (! nextresult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
rv = mProcessor->AddMemoryElements(*inst, nextresult);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mProcessor->GetBuilder()->AddResult(nextresult, querynode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsresult rv = mQuery->SetCachedResults(mProcessor, aInstantiations);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
aTakenInstantiations = true;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsInstantiationNode_h__
|
||||
#define nsInstantiationNode_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsRDFQuery.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorRDF;
|
||||
|
||||
/**
|
||||
* A leaf-level node in the rule network. If any instantiations
|
||||
* propagate to this node, then we know we've matched a rule.
|
||||
*/
|
||||
class nsInstantiationNode : public ReteNode
|
||||
{
|
||||
public:
|
||||
nsInstantiationNode(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsRDFQuery* aRule);
|
||||
|
||||
~nsInstantiationNode();
|
||||
|
||||
// "downward" propagations
|
||||
virtual nsresult Propagate(InstantiationSet& aInstantiations,
|
||||
bool aIsUpdate, bool& aMatched) override;
|
||||
|
||||
protected:
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
nsRDFQuery* mQuery;
|
||||
};
|
||||
|
||||
#endif // nsInstantiationNode_h__
|
@ -1,265 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
#include "nsXULTemplateResultRDF.h"
|
||||
#include "nsRDFBinding.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "nsXULContentUtils.h"
|
||||
#endif
|
||||
|
||||
RDFBindingSet::~RDFBindingSet()
|
||||
{
|
||||
while (mFirst) {
|
||||
RDFBinding* doomed = mFirst;
|
||||
mFirst = mFirst->mNext;
|
||||
delete doomed;
|
||||
}
|
||||
|
||||
MOZ_COUNT_DTOR(RDFBindingSet);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RDFBindingSet::AddBinding(nsAtom* aVar, nsAtom* aRef, nsIRDFResource* aPredicate)
|
||||
{
|
||||
RDFBinding* newbinding = new RDFBinding(aRef, aPredicate, aVar);
|
||||
if (mFirst) {
|
||||
RDFBinding* binding = mFirst;
|
||||
|
||||
while (binding) {
|
||||
// the binding is dependant on the calculation of a previous binding
|
||||
if (binding->mSubjectVariable == aVar)
|
||||
newbinding->mHasDependency = true;
|
||||
|
||||
// if the target variable is already used in a binding, ignore it
|
||||
// since it won't be useful for anything
|
||||
if (binding->mTargetVariable == aVar) {
|
||||
delete newbinding;
|
||||
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;
|
||||
}
|
||||
|
||||
mCount++;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
RDFBindingSet::SyncAssignments(nsIRDFResource* aSubject,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsIRDFNode* aTarget,
|
||||
nsAtom* aMemberVariable,
|
||||
nsXULTemplateResultRDF* aResult,
|
||||
nsBindingValues& aBindingValues)
|
||||
{
|
||||
NS_ASSERTION(aBindingValues.GetBindingSet() == this,
|
||||
"nsBindingValues not for this RDFBindingSet");
|
||||
NS_PRECONDITION(aResult, "Must have result");
|
||||
|
||||
bool needSync = false;
|
||||
nsCOMPtr<nsIRDFNode>* valuesArray = aBindingValues.ValuesArray();
|
||||
if (!valuesArray)
|
||||
return false;
|
||||
|
||||
RDFBinding* binding = mFirst;
|
||||
int32_t count = 0;
|
||||
|
||||
// QI for proper comparisons just to be safe
|
||||
nsCOMPtr<nsIRDFNode> subjectnode = do_QueryInterface(aSubject);
|
||||
|
||||
// iterate through the bindings looking for ones that would match the RDF
|
||||
// nodes that were involved in a change
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
while (binding) {
|
||||
if (aPredicate == binding->mPredicate) {
|
||||
// if the source of the binding is the member variable, optimize
|
||||
if (binding->mSubjectVariable == aMemberVariable) {
|
||||
valuesArray[count] = aTarget;
|
||||
needSync = true;
|
||||
}
|
||||
else {
|
||||
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
||||
if (value == subjectnode) {
|
||||
valuesArray[count] = aTarget;
|
||||
needSync = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
binding = binding->mNext;
|
||||
count++;
|
||||
}
|
||||
|
||||
return needSync;
|
||||
}
|
||||
|
||||
void
|
||||
RDFBindingSet::AddDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "Must have result");
|
||||
|
||||
// iterate through the bindings and add binding dependencies to the
|
||||
// processor
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
||||
if (! processor)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
|
||||
RDFBinding* binding = mFirst;
|
||||
while (binding) {
|
||||
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
|
||||
if (valueres)
|
||||
processor->AddBindingDependency(aResult, valueres);
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RDFBindingSet::RemoveDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult, "Must have result");
|
||||
|
||||
// iterate through the bindings and remove binding dependencies from the
|
||||
// processor
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
||||
if (! processor)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
|
||||
RDFBinding* binding = mFirst;
|
||||
while (binding) {
|
||||
aResult->GetAssignment(binding->mSubjectVariable, getter_AddRefs(value));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
|
||||
if (valueres)
|
||||
processor->RemoveBindingDependency(aResult, valueres);
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
RDFBindingSet::LookupTargetIndex(nsAtom* aTargetVariable, RDFBinding** aBinding)
|
||||
{
|
||||
int32_t idx = 0;
|
||||
RDFBinding* binding = mFirst;
|
||||
|
||||
while (binding) {
|
||||
if (binding->mTargetVariable == aTargetVariable) {
|
||||
*aBinding = binding;
|
||||
return idx;
|
||||
}
|
||||
idx++;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
nsBindingValues::~nsBindingValues()
|
||||
{
|
||||
ClearBindingSet();
|
||||
MOZ_COUNT_DTOR(nsBindingValues);
|
||||
}
|
||||
|
||||
void
|
||||
nsBindingValues::ClearBindingSet()
|
||||
{
|
||||
if (mBindings && mValues) {
|
||||
delete [] mValues;
|
||||
mValues = nullptr;
|
||||
}
|
||||
|
||||
mBindings = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsBindingValues::SetBindingSet(RDFBindingSet* aBindings)
|
||||
{
|
||||
ClearBindingSet();
|
||||
|
||||
int32_t count = aBindings->Count();
|
||||
if (count) {
|
||||
mValues = new nsCOMPtr<nsIRDFNode>[count];
|
||||
mBindings = aBindings;
|
||||
}
|
||||
else {
|
||||
mValues = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsBindingValues::GetAssignmentFor(nsXULTemplateResultRDF* aResult,
|
||||
nsAtom* aVar,
|
||||
nsIRDFNode** aValue)
|
||||
{
|
||||
*aValue = nullptr;
|
||||
|
||||
// assignments are calculated lazily when asked for. The only issue is
|
||||
// when a binding has no value in the RDF graph, it will be checked again
|
||||
// every time.
|
||||
|
||||
if (mBindings && mValues) {
|
||||
RDFBinding* binding;
|
||||
int32_t idx = mBindings->LookupTargetIndex(aVar, &binding);
|
||||
if (idx >= 0) {
|
||||
*aValue = mValues[idx];
|
||||
if (*aValue) {
|
||||
NS_ADDREF(*aValue);
|
||||
}
|
||||
else {
|
||||
nsXULTemplateQueryProcessorRDF* processor = aResult->GetProcessor();
|
||||
if (! processor)
|
||||
return;
|
||||
|
||||
nsIRDFDataSource* ds = processor->GetDataSource();
|
||||
if (! ds)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> subjectValue;
|
||||
aResult->GetAssignment(binding->mSubjectVariable,
|
||||
getter_AddRefs(subjectValue));
|
||||
if (subjectValue) {
|
||||
nsCOMPtr<nsIRDFResource> subject = do_QueryInterface(subjectValue);
|
||||
ds->GetTarget(subject, binding->mPredicate, true, aValue);
|
||||
if (*aValue)
|
||||
mValues[idx] = *aValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsBindingValues::RemoveDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult)
|
||||
{
|
||||
if (mBindings)
|
||||
mBindings->RemoveDependencies(aSubject, aResult);
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFBinding_h__
|
||||
#define nsRDFBinding_h__
|
||||
|
||||
#include "nsAtom.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
class nsXULTemplateResultRDF;
|
||||
class nsBindingValues;
|
||||
|
||||
/*
|
||||
* Classes related to storing bindings for RDF handling.
|
||||
*/
|
||||
|
||||
/*
|
||||
* a <binding> descriptors
|
||||
*/
|
||||
class RDFBinding {
|
||||
|
||||
public:
|
||||
|
||||
RefPtr<nsAtom> mSubjectVariable;
|
||||
nsCOMPtr<nsIRDFResource> mPredicate;
|
||||
RefPtr<nsAtom> mTargetVariable;
|
||||
|
||||
// indicates whether a binding is dependant on the result from a
|
||||
// previous binding
|
||||
bool mHasDependency;
|
||||
|
||||
RDFBinding* mNext;
|
||||
|
||||
private:
|
||||
|
||||
friend class RDFBindingSet;
|
||||
|
||||
RDFBinding(nsAtom* aSubjectVariable,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsAtom* aTargetVariable)
|
||||
: mSubjectVariable(aSubjectVariable),
|
||||
mPredicate(aPredicate),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mHasDependency(false),
|
||||
mNext(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RDFBinding);
|
||||
}
|
||||
|
||||
~RDFBinding()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RDFBinding);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* a collection of <binding> descriptors. This object is refcounted by
|
||||
* nsBindingValues objects and the query processor.
|
||||
*/
|
||||
class RDFBindingSet final
|
||||
{
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~RDFBindingSet();
|
||||
|
||||
// the number of bindings
|
||||
int32_t mCount;
|
||||
|
||||
// pointer to the first binding in a linked list
|
||||
RDFBinding* mFirst;
|
||||
|
||||
public:
|
||||
|
||||
RDFBindingSet()
|
||||
: mCount(0),
|
||||
mFirst(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(RDFBindingSet);
|
||||
}
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(RDFBindingSet)
|
||||
|
||||
int32_t Count() const { return mCount; }
|
||||
|
||||
/*
|
||||
* Add a binding (aRef -> aPredicate -> aVar) to the set
|
||||
*/
|
||||
nsresult
|
||||
AddBinding(nsAtom* aVar, nsAtom* aRef, nsIRDFResource* aPredicate);
|
||||
|
||||
/*
|
||||
* Return true if the binding set contains a binding which would cause
|
||||
* the result to need resynchronizing for an RDF triple. The member
|
||||
* variable may be supplied as an optimization since bindings most
|
||||
* commonly use the member variable as the subject. If aMemberVariable
|
||||
* is set, aSubject must be the value of the member variable for the
|
||||
* result. The supplied binding values aBindingValues must be values
|
||||
* using this binding set (that is aBindingValues->GetBindingSet() == this)
|
||||
*
|
||||
* @param aSubject subject of the RDF triple
|
||||
* @param aPredicate predicate of the RDF triple
|
||||
* @param aTarget target of the RDF triple
|
||||
* @param aMemberVariable member variable for the query for the binding
|
||||
* @param aResult result to synchronize
|
||||
* @param aBindingValues the values for the bindings for the result
|
||||
*/
|
||||
bool
|
||||
SyncAssignments(nsIRDFResource* aSubject,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsIRDFNode* aTarget,
|
||||
nsAtom* aMemberVariable,
|
||||
nsXULTemplateResultRDF* aResult,
|
||||
nsBindingValues& aBindingValues);
|
||||
|
||||
/*
|
||||
* The query processor maintains a map of subjects to an array of results.
|
||||
* This is used such that when a new assertion is added to the RDF graph,
|
||||
* the results associated with the subject of that triple may be checked
|
||||
* to see if their bindings have changed. The AddDependencies method adds
|
||||
* these subject dependencies to the map.
|
||||
*/
|
||||
void
|
||||
AddDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult);
|
||||
|
||||
/*
|
||||
* Remove the results from the dependencies map when results are deleted.
|
||||
*/
|
||||
void
|
||||
RemoveDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult);
|
||||
|
||||
/*
|
||||
* The nsBindingValues classes 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.
|
||||
*/
|
||||
int32_t
|
||||
LookupTargetIndex(nsAtom* aTargetVariable, RDFBinding** aBinding);
|
||||
};
|
||||
|
||||
/*
|
||||
* A set of values of bindings. This object is used once per result.
|
||||
* This stores a reference to the binding set and an array of node values.
|
||||
* Since the binding set is used once per query and the values are
|
||||
* used once per result, we reduce size by only storing the value array's
|
||||
* length in the binding set. This is possible since the array is always
|
||||
* a fixed length for a particular binding set.
|
||||
*
|
||||
* XXX ndeakin We may want to revisit this later since it makes the code
|
||||
* more complicated.
|
||||
*/
|
||||
class nsBindingValues
|
||||
{
|
||||
protected:
|
||||
|
||||
// the binding set
|
||||
RefPtr<RDFBindingSet> 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. The size of this
|
||||
* array is determined by the RDFBindingSet's Count().
|
||||
*/
|
||||
nsCOMPtr<nsIRDFNode>* mValues;
|
||||
|
||||
public:
|
||||
|
||||
nsBindingValues()
|
||||
: mBindings(nullptr),
|
||||
mValues(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsBindingValues);
|
||||
}
|
||||
|
||||
~nsBindingValues();
|
||||
|
||||
|
||||
/**
|
||||
* Clear the binding set, to be called when the nsBindingValues is deleted
|
||||
* or a new binding set is being set.
|
||||
*/
|
||||
void ClearBindingSet();
|
||||
|
||||
RDFBindingSet* GetBindingSet() { return mBindings; }
|
||||
|
||||
/**
|
||||
* Set the binding set to use. This needs to be called once a rule matches
|
||||
* since it is then known which bindings will apply.
|
||||
*/
|
||||
nsresult SetBindingSet(RDFBindingSet* aBindings);
|
||||
|
||||
nsCOMPtr<nsIRDFNode>* ValuesArray() { return mValues; }
|
||||
|
||||
/*
|
||||
* Retrieve the assignment for a particular variable
|
||||
*/
|
||||
void
|
||||
GetAssignmentFor(nsXULTemplateResultRDF* aResult,
|
||||
nsAtom* aVar,
|
||||
nsIRDFNode** aValue);
|
||||
|
||||
/*
|
||||
* Remove depenedencies the bindings have on particular resources
|
||||
*/
|
||||
void
|
||||
RemoveDependencies(nsIRDFResource* aSubject,
|
||||
nsXULTemplateResultRDF* aResult);
|
||||
};
|
||||
|
||||
#endif // nsRDFBinding_h__
|
@ -1,281 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsRDFConInstanceTestNode.h"
|
||||
#include "nsResourceSet.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
|
||||
using mozilla::LogLevel;
|
||||
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
static const char*
|
||||
TestToString(nsRDFConInstanceTestNode::Test aTest) {
|
||||
switch (aTest) {
|
||||
case nsRDFConInstanceTestNode::eFalse: return "false";
|
||||
case nsRDFConInstanceTestNode::eTrue: return "true";
|
||||
case nsRDFConInstanceTestNode::eDontCare: return "dontcare";
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
|
||||
nsRDFConInstanceTestNode::nsRDFConInstanceTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aContainerVariable,
|
||||
Test aContainer,
|
||||
Test aEmpty)
|
||||
: nsRDFTestNode(aParent),
|
||||
mProcessor(aProcessor),
|
||||
mContainerVariable(aContainerVariable),
|
||||
mContainer(aContainer),
|
||||
mEmpty(aEmpty)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoCString props;
|
||||
|
||||
nsResourceSet& containmentProps = aProcessor->ContainmentProperties();
|
||||
nsResourceSet::ConstIterator last = containmentProps.Last();
|
||||
nsResourceSet::ConstIterator first = containmentProps.First();
|
||||
nsResourceSet::ConstIterator iter;
|
||||
|
||||
for (iter = first; iter != last; ++iter) {
|
||||
if (iter != first)
|
||||
props += " ";
|
||||
|
||||
const char* str;
|
||||
iter->GetValueConst(&str);
|
||||
|
||||
props += str;
|
||||
}
|
||||
|
||||
nsAutoString cvar(NS_LITERAL_STRING("(none)"));
|
||||
if (mContainerVariable)
|
||||
mContainerVariable->ToString(cvar);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConInstanceTestNode[%p]: parent=%p member-props=(%s) container-var=%s container=%s empty=%s",
|
||||
this,
|
||||
aParent,
|
||||
props.get(),
|
||||
NS_ConvertUTF16toUTF8(cvar).get(),
|
||||
TestToString(aContainer),
|
||||
TestToString(aEmpty)));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRDFConInstanceTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aCantHandleYet)
|
||||
*aCantHandleYet = false;
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> rdfc
|
||||
= do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
|
||||
if (! rdfc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIRDFDataSource* ds = mProcessor->GetDataSource();
|
||||
|
||||
InstantiationSet::Iterator last = aInstantiations.Last();
|
||||
for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
if (! inst->mAssignments.GetAssignmentFor(mContainerVariable, getter_AddRefs(value))) {
|
||||
NS_ERROR("can't do unbounded container testing");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> valueres = do_QueryInterface(value);
|
||||
if (! valueres) {
|
||||
aInstantiations.Erase(inst--);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* container = "(unbound)";
|
||||
valueres->GetValueConst(&container);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConInstanceTestNode[%p]::FilterInstantiations() container=[%s]",
|
||||
this, container));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFContainer> rdfcontainer;
|
||||
|
||||
bool isRDFContainer;
|
||||
rv = rdfc->IsContainer(ds, valueres, &isRDFContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mEmpty != eDontCare || mContainer != eDontCare) {
|
||||
Test empty = eDontCare;
|
||||
Test container = eDontCare;
|
||||
|
||||
if (isRDFContainer) {
|
||||
// It's an RDF container. Use the container utilities
|
||||
// to deduce what's in it.
|
||||
container = eTrue;
|
||||
|
||||
// XXX should cache the factory
|
||||
rdfcontainer = do_CreateInstance("@mozilla.org/rdf/container;1", &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = rdfcontainer->Init(ds, valueres);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
int32_t count;
|
||||
rv = rdfcontainer->GetCount(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
empty = (count == 0) ? eTrue : eFalse;
|
||||
} else {
|
||||
empty = eTrue;
|
||||
container = eFalse;
|
||||
|
||||
// First do the simple check of finding some outward
|
||||
// arcs; there should be only a few containment arcs, so this can
|
||||
// save us time from dealing with an iterator later on
|
||||
nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
|
||||
for (nsResourceSet::ConstIterator property = containmentProps.First();
|
||||
property != containmentProps.Last();
|
||||
++property) {
|
||||
nsCOMPtr<nsIRDFNode> target;
|
||||
rv = ds->GetTarget(valueres, *property, true, getter_AddRefs(target));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (target != nullptr) {
|
||||
// bingo. we found one.
|
||||
empty = eFalse;
|
||||
container = eTrue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if we still don't think its a container, but we
|
||||
// want to know for sure whether it is or not, we need
|
||||
// to check ArcLabelsOut for potential container arcs.
|
||||
if (container == eFalse && mContainer != eDontCare) {
|
||||
nsCOMPtr<nsISimpleEnumerator> arcsout;
|
||||
rv = ds->ArcLabelsOut(valueres, getter_AddRefs(arcsout));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
bool hasmore;
|
||||
rv = arcsout->HasMoreElements(&hasmore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasmore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = arcsout->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> property = do_QueryInterface(isupports);
|
||||
NS_ASSERTION(property != nullptr, "not a property");
|
||||
if (! property)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (mProcessor->ContainmentProperties().Contains(property)) {
|
||||
container = eTrue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" empty => %s",
|
||||
(empty == mEmpty) ? "consistent" : "inconsistent"));
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" container => %s",
|
||||
(container == mContainer) ? "consistent" : "inconsistent"));
|
||||
|
||||
if (((mEmpty == empty) && (mContainer == container)) ||
|
||||
((mEmpty == eDontCare) && (mContainer == container)) ||
|
||||
((mContainer == eDontCare) && (mEmpty == empty)))
|
||||
{
|
||||
Element* element =
|
||||
new nsRDFConInstanceTestNode::Element(valueres, container, empty);
|
||||
inst->AddSupportingElement(element);
|
||||
}
|
||||
else {
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsRDFConInstanceTestNode::CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
bool canpropagate = false;
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> rdfc
|
||||
= do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
|
||||
if (! rdfc)
|
||||
return false;
|
||||
|
||||
// We can certainly propagate ordinal properties
|
||||
rv = rdfc->IsOrdinalProperty(aProperty, &canpropagate);
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
if (! canpropagate) {
|
||||
canpropagate = mProcessor->ContainmentProperties().Contains(aProperty);
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source;
|
||||
aSource->GetValueConst(&source);
|
||||
|
||||
const char* property;
|
||||
aProperty->GetValueConst(&property);
|
||||
|
||||
nsAutoString target;
|
||||
nsXULContentUtils::GetTextForNode(aTarget, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConInstanceTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
|
||||
this, source, property, NS_ConvertUTF16toUTF8(target).get(),
|
||||
canpropagate ? "true" : "false"));
|
||||
}
|
||||
|
||||
if (canpropagate) {
|
||||
aInitialBindings.AddAssignment(mContainerVariable, aSource);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsRDFConInstanceTestNode::Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const
|
||||
{
|
||||
// XXXwaterson oof. complicated. figure this out.
|
||||
if (0) {
|
||||
mProcessor->RetractElement(Element(aSource, mContainer, mEmpty));
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFConInstanceTestNode_h__
|
||||
#define nsRDFConInstanceTestNode_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nscore.h"
|
||||
#include "nsRDFTestNode.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
/**
|
||||
* Rule network node that tests if a resource is an RDF container, or
|
||||
* uses multi-attributes to ``contain'' other elements.
|
||||
*/
|
||||
class nsRDFConInstanceTestNode : public nsRDFTestNode
|
||||
{
|
||||
public:
|
||||
enum Test { eFalse, eTrue, eDontCare };
|
||||
|
||||
nsRDFConInstanceTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aContainerVariable,
|
||||
Test aContainer,
|
||||
Test aEmpty);
|
||||
|
||||
virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const override;
|
||||
|
||||
virtual bool
|
||||
CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const override;
|
||||
|
||||
virtual void
|
||||
Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const override;
|
||||
|
||||
|
||||
class Element : public MemoryElement {
|
||||
public:
|
||||
Element(nsIRDFResource* aContainer,
|
||||
Test aContainerTest,
|
||||
Test aEmptyTest)
|
||||
: mContainer(aContainer),
|
||||
mContainerTest(aContainerTest),
|
||||
mEmptyTest(aEmptyTest) {
|
||||
MOZ_COUNT_CTOR(nsRDFConInstanceTestNode::Element); }
|
||||
|
||||
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConInstanceTestNode::Element); }
|
||||
|
||||
virtual const char* Type() const override {
|
||||
return "nsRDFConInstanceTestNode::Element"; }
|
||||
|
||||
virtual PLHashNumber Hash() const override {
|
||||
return mozilla::HashGeneric(mContainerTest, mEmptyTest, mContainer.get());
|
||||
}
|
||||
|
||||
virtual bool Equals(const MemoryElement& aElement) const override {
|
||||
if (aElement.Type() == Type()) {
|
||||
const Element& element = static_cast<const Element&>(aElement);
|
||||
return mContainer == element.mContainer
|
||||
&& mContainerTest == element.mContainerTest
|
||||
&& mEmptyTest == element.mEmptyTest;
|
||||
}
|
||||
return false; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIRDFResource> mContainer;
|
||||
Test mContainerTest;
|
||||
Test mEmptyTest;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
RefPtr<nsAtom> mContainerVariable;
|
||||
Test mContainer;
|
||||
Test mEmpty;
|
||||
};
|
||||
|
||||
#endif // nsRDFConInstanceTestNode_h__
|
||||
|
@ -1,510 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsRDFConMemberTestNode.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsResourceSet.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
using mozilla::LogLevel;
|
||||
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
nsRDFConMemberTestNode::nsRDFConMemberTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom *aContainerVariable,
|
||||
nsAtom *aMemberVariable)
|
||||
: nsRDFTestNode(aParent),
|
||||
mProcessor(aProcessor),
|
||||
mContainerVariable(aContainerVariable),
|
||||
mMemberVariable(aMemberVariable)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoCString props;
|
||||
|
||||
nsResourceSet& containmentProps = aProcessor->ContainmentProperties();
|
||||
nsResourceSet::ConstIterator last = containmentProps.Last();
|
||||
nsResourceSet::ConstIterator first = containmentProps.First();
|
||||
nsResourceSet::ConstIterator iter;
|
||||
|
||||
for (iter = first; iter != last; ++iter) {
|
||||
if (iter != first)
|
||||
props += " ";
|
||||
|
||||
const char* str;
|
||||
iter->GetValueConst(&str);
|
||||
|
||||
props += str;
|
||||
}
|
||||
|
||||
nsAutoString cvar(NS_LITERAL_STRING("(none)"));
|
||||
if (mContainerVariable)
|
||||
mContainerVariable->ToString(cvar);
|
||||
|
||||
nsAutoString mvar(NS_LITERAL_STRING("(none)"));
|
||||
if (mMemberVariable)
|
||||
mMemberVariable->ToString(mvar);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConMemberTestNode[%p]: parent=%p member-props=(%s) container-var=%s member-var=%s",
|
||||
this,
|
||||
aParent,
|
||||
props.get(),
|
||||
NS_ConvertUTF16toUTF8(cvar).get(),
|
||||
NS_ConvertUTF16toUTF8(mvar).get()));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const
|
||||
{
|
||||
// XXX Uh, factor me, please!
|
||||
nsresult rv;
|
||||
|
||||
if (aCantHandleYet)
|
||||
*aCantHandleYet = false;
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> rdfc =
|
||||
do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
|
||||
if (! rdfc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIRDFDataSource* ds = mProcessor->GetDataSource();
|
||||
|
||||
InstantiationSet::Iterator last = aInstantiations.Last();
|
||||
for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
|
||||
bool hasContainerBinding;
|
||||
nsCOMPtr<nsIRDFNode> containerValue;
|
||||
hasContainerBinding = inst->mAssignments.GetAssignmentFor(mContainerVariable,
|
||||
getter_AddRefs(containerValue));
|
||||
|
||||
nsCOMPtr<nsIRDFResource> containerRes = do_QueryInterface(containerValue);
|
||||
|
||||
nsCOMPtr<nsIRDFContainer> rdfcontainer;
|
||||
|
||||
if (hasContainerBinding && containerRes) {
|
||||
// If we have a container assignment, then see if the
|
||||
// container is an RDF container (bag, seq, alt), and if
|
||||
// so, wrap it.
|
||||
bool isRDFContainer;
|
||||
rv = rdfc->IsContainer(ds, containerRes, &isRDFContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (isRDFContainer) {
|
||||
rdfcontainer = do_CreateInstance("@mozilla.org/rdf/container;1", &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = rdfcontainer->Init(ds, containerRes);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
bool hasMemberBinding;
|
||||
nsCOMPtr<nsIRDFNode> memberValue;
|
||||
hasMemberBinding = inst->mAssignments.GetAssignmentFor(mMemberVariable,
|
||||
getter_AddRefs(memberValue));
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* container = "(unbound)";
|
||||
if (hasContainerBinding)
|
||||
containerRes->GetValueConst(&container);
|
||||
|
||||
nsAutoString member(NS_LITERAL_STRING("(unbound)"));
|
||||
if (hasMemberBinding)
|
||||
nsXULContentUtils::GetTextForNode(memberValue, member);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConMemberTestNode[%p]: FilterInstantiations() container=[%s] member=[%s]",
|
||||
this, container, NS_ConvertUTF16toUTF8(member).get()));
|
||||
}
|
||||
|
||||
if (hasContainerBinding && hasMemberBinding) {
|
||||
// it's a consistency check. see if we have a assignment that is consistent
|
||||
bool isconsistent = false;
|
||||
|
||||
if (rdfcontainer) {
|
||||
// RDF containers are easy. Just use the container API.
|
||||
int32_t index;
|
||||
rv = rdfcontainer->IndexOf(memberValue, &index);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (index >= 0)
|
||||
isconsistent = true;
|
||||
}
|
||||
|
||||
// XXXwaterson oof. if we *are* an RDF container, why do
|
||||
// we still need to grovel through all the containment
|
||||
// properties if the thing we're looking for wasn't there?
|
||||
|
||||
if (! isconsistent) {
|
||||
// Othewise, we'll need to grovel through the
|
||||
// membership properties to see if we have an
|
||||
// assertion that indicates membership.
|
||||
nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
|
||||
for (nsResourceSet::ConstIterator property = containmentProps.First();
|
||||
property != containmentProps.Last();
|
||||
++property) {
|
||||
bool hasAssertion;
|
||||
rv = ds->HasAssertion(containerRes,
|
||||
*property,
|
||||
memberValue,
|
||||
true,
|
||||
&hasAssertion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (hasAssertion) {
|
||||
// it's consistent. leave it in the set and we'll
|
||||
// run it up to our parent.
|
||||
isconsistent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" consistency check => %s", isconsistent ? "passed" : "failed"));
|
||||
|
||||
if (isconsistent) {
|
||||
// Add a memory element to our set-of-support.
|
||||
Element* element =
|
||||
new nsRDFConMemberTestNode::Element(containerRes,
|
||||
memberValue);
|
||||
inst->AddSupportingElement(element);
|
||||
}
|
||||
else {
|
||||
// it's inconsistent. remove it.
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
|
||||
// We're done, go on to the next instantiation
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hasContainerBinding && rdfcontainer) {
|
||||
// We've got a container assignment, and the container is
|
||||
// bound to an RDF container. Add each member as a new
|
||||
// instantiation.
|
||||
nsCOMPtr<nsISimpleEnumerator> elements;
|
||||
rv = rdfcontainer->GetElements(getter_AddRefs(elements));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
bool hasmore;
|
||||
rv = elements->HasMoreElements(&hasmore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasmore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = elements->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> node = do_QueryInterface(isupports);
|
||||
if (! node)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoString member;
|
||||
nsXULContentUtils::GetTextForNode(node, member);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" member => %s", NS_ConvertUTF16toUTF8(member).get()));
|
||||
}
|
||||
|
||||
Instantiation newinst = *inst;
|
||||
newinst.AddAssignment(mMemberVariable, node);
|
||||
|
||||
Element* element =
|
||||
new nsRDFConMemberTestNode::Element(containerRes, node);
|
||||
newinst.AddSupportingElement(element);
|
||||
aInstantiations.Insert(inst, newinst);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasMemberBinding) {
|
||||
// Oh, this is so nasty. If we have a member assignment, then
|
||||
// grovel through each one of our inbound arcs to see if
|
||||
// any of them are ordinal properties (like an RDF
|
||||
// container might have). If so, walk it backwards to get
|
||||
// the container we're in.
|
||||
nsCOMPtr<nsISimpleEnumerator> arcsin;
|
||||
rv = ds->ArcLabelsIn(memberValue, getter_AddRefs(arcsin));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
nsCOMPtr<nsIRDFResource> property;
|
||||
|
||||
{
|
||||
bool hasmore;
|
||||
rv = arcsin->HasMoreElements(&hasmore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasmore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = arcsin->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
property = do_QueryInterface(isupports);
|
||||
if (! property)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Ordinal properties automagically indicate container
|
||||
// membership as far as we're concerned. Note that
|
||||
// we're *only* concerned with ordinal properties
|
||||
// here: the next block will worry about the other
|
||||
// membership properties.
|
||||
bool isordinal;
|
||||
rv = rdfc->IsOrdinalProperty(property, &isordinal);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (isordinal) {
|
||||
// If we get here, we've found a property that
|
||||
// indicates container membership leading *into* a
|
||||
// member node. Find all the people that point to
|
||||
// it, and call them containers.
|
||||
nsCOMPtr<nsISimpleEnumerator> sources;
|
||||
rv = ds->GetSources(property, memberValue, true,
|
||||
getter_AddRefs(sources));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
bool hasmore;
|
||||
rv = sources->HasMoreElements(&hasmore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasmore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = sources->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports);
|
||||
if (! source)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* container;
|
||||
source->GetValueConst(&container);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" container => %s", container));
|
||||
}
|
||||
|
||||
// Add a new instantiation
|
||||
Instantiation newinst = *inst;
|
||||
newinst.AddAssignment(mContainerVariable, source);
|
||||
|
||||
Element* element =
|
||||
new nsRDFConMemberTestNode::Element(source,
|
||||
memberValue);
|
||||
newinst.AddSupportingElement(element);
|
||||
|
||||
aInstantiations.Insert(inst, newinst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((hasContainerBinding && ! hasMemberBinding) ||
|
||||
(! hasContainerBinding && hasMemberBinding)) {
|
||||
// it's an open ended query on the container or member. go
|
||||
// through our containment properties to see if anything
|
||||
// applies.
|
||||
nsResourceSet& containmentProps = mProcessor->ContainmentProperties();
|
||||
for (nsResourceSet::ConstIterator property = containmentProps.First();
|
||||
property != containmentProps.Last();
|
||||
++property) {
|
||||
nsCOMPtr<nsISimpleEnumerator> results;
|
||||
if (hasContainerBinding) {
|
||||
rv = ds->GetTargets(containerRes, *property, true,
|
||||
getter_AddRefs(results));
|
||||
}
|
||||
else {
|
||||
rv = ds->GetSources(*property, memberValue, true,
|
||||
getter_AddRefs(results));
|
||||
}
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
bool hasmore;
|
||||
rv = results->HasMoreElements(&hasmore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasmore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = results->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAtom* variable;
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
nsCOMPtr<nsIRDFResource> valueRes;
|
||||
|
||||
if (hasContainerBinding) {
|
||||
variable = mMemberVariable;
|
||||
|
||||
value = do_QueryInterface(isupports);
|
||||
NS_ASSERTION(value != nullptr, "member is not an nsIRDFNode");
|
||||
if (! value) continue;
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoString s;
|
||||
nsXULContentUtils::GetTextForNode(value, s);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" member => %s", NS_ConvertUTF16toUTF8(s).get()));
|
||||
}
|
||||
}
|
||||
else {
|
||||
variable = mContainerVariable;
|
||||
|
||||
valueRes = do_QueryInterface(isupports);
|
||||
NS_ASSERTION(valueRes != nullptr, "container is not an nsIRDFResource");
|
||||
if (! valueRes) continue;
|
||||
|
||||
value = valueRes;
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* s;
|
||||
valueRes->GetValueConst(&s);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" container => %s", s));
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the original instantiation, and add it to the
|
||||
// instantiation set with the new assignment that we've
|
||||
// introduced. Ownership will be transferred to the
|
||||
Instantiation newinst = *inst;
|
||||
newinst.AddAssignment(variable, value);
|
||||
|
||||
Element* element;
|
||||
if (hasContainerBinding) {
|
||||
element =
|
||||
new nsRDFConMemberTestNode::Element(containerRes, value);
|
||||
}
|
||||
else {
|
||||
element =
|
||||
new nsRDFConMemberTestNode::Element(valueRes, memberValue);
|
||||
}
|
||||
|
||||
if (! element)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
newinst.AddSupportingElement(element);
|
||||
|
||||
aInstantiations.Insert(inst, newinst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! hasContainerBinding && ! hasMemberBinding) {
|
||||
// Neither container nor member assignment!
|
||||
if (!aCantHandleYet) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_MEMBER_UNBOUND);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
*aCantHandleYet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// finally, remove the "under specified" instantiation.
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsRDFConMemberTestNode::CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
bool canpropagate = false;
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> rdfc =
|
||||
do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
|
||||
if (! rdfc)
|
||||
return false;
|
||||
|
||||
// We can certainly propagate ordinal properties
|
||||
rv = rdfc->IsOrdinalProperty(aProperty, &canpropagate);
|
||||
if (NS_FAILED(rv)) return false;
|
||||
|
||||
if (! canpropagate) {
|
||||
canpropagate = mProcessor->ContainmentProperties().Contains(aProperty);
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source;
|
||||
aSource->GetValueConst(&source);
|
||||
|
||||
const char* property;
|
||||
aProperty->GetValueConst(&property);
|
||||
|
||||
nsAutoString target;
|
||||
nsXULContentUtils::GetTextForNode(aTarget, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFConMemberTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
|
||||
this, source, property, NS_ConvertUTF16toUTF8(target).get(),
|
||||
canpropagate ? "true" : "false"));
|
||||
}
|
||||
|
||||
if (canpropagate) {
|
||||
aInitialBindings.AddAssignment(mContainerVariable, aSource);
|
||||
aInitialBindings.AddAssignment(mMemberVariable, aTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
nsRDFConMemberTestNode::Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const
|
||||
{
|
||||
bool canretract = false;
|
||||
|
||||
nsCOMPtr<nsIRDFContainerUtils> rdfc =
|
||||
do_GetService("@mozilla.org/rdf/container-utils;1");
|
||||
|
||||
if (! rdfc)
|
||||
return;
|
||||
|
||||
// We can certainly retract ordinal properties
|
||||
nsresult rv;
|
||||
rv = rdfc->IsOrdinalProperty(aProperty, &canretract);
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
if (! canretract) {
|
||||
canretract = mProcessor->ContainmentProperties().Contains(aProperty);
|
||||
}
|
||||
|
||||
if (canretract) {
|
||||
mProcessor->RetractElement(Element(aSource, aTarget));
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFConMemberTestNode_h__
|
||||
#define nsRDFConMemberTestNode_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nscore.h"
|
||||
#include "nsRDFTestNode.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
/**
|
||||
* Rule network node that test if a resource is a member of an RDF
|
||||
* container, or is ``contained'' by another resource that refers to
|
||||
* it using a ``containment'' attribute.
|
||||
*/
|
||||
class nsRDFConMemberTestNode : public nsRDFTestNode
|
||||
{
|
||||
public:
|
||||
nsRDFConMemberTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aContainerVariable,
|
||||
nsAtom* aMemberVariable);
|
||||
|
||||
virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const override;
|
||||
|
||||
virtual bool
|
||||
CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const override;
|
||||
|
||||
virtual void
|
||||
Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const override;
|
||||
|
||||
class Element : public MemoryElement {
|
||||
public:
|
||||
Element(nsIRDFResource* aContainer,
|
||||
nsIRDFNode* aMember)
|
||||
: mContainer(aContainer),
|
||||
mMember(aMember) {
|
||||
MOZ_COUNT_CTOR(nsRDFConMemberTestNode::Element); }
|
||||
|
||||
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFConMemberTestNode::Element); }
|
||||
|
||||
virtual const char* Type() const override {
|
||||
return "nsRDFConMemberTestNode::Element"; }
|
||||
|
||||
virtual PLHashNumber Hash() const override {
|
||||
return PLHashNumber(NS_PTR_TO_INT32(mContainer.get())) ^
|
||||
(PLHashNumber(NS_PTR_TO_INT32(mMember.get())) >> 12); }
|
||||
|
||||
virtual bool Equals(const MemoryElement& aElement) const override {
|
||||
if (aElement.Type() == Type()) {
|
||||
const Element& element = static_cast<const Element&>(aElement);
|
||||
return mContainer == element.mContainer && mMember == element.mMember;
|
||||
}
|
||||
return false; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIRDFResource> mContainer;
|
||||
nsCOMPtr<nsIRDFNode> mMember;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
RefPtr<nsAtom> mContainerVariable;
|
||||
RefPtr<nsAtom> mMemberVariable;
|
||||
};
|
||||
|
||||
#endif // nsRDFConMemberTestNode_h__
|
@ -1,362 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsRDFPropertyTestNode.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
using mozilla::LogLevel;
|
||||
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
#include "nsIRDFLiteral.h"
|
||||
|
||||
nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aSourceVariable,
|
||||
nsIRDFResource* aProperty,
|
||||
nsAtom* aTargetVariable)
|
||||
: nsRDFTestNode(aParent),
|
||||
mProcessor(aProcessor),
|
||||
mSourceVariable(aSourceVariable),
|
||||
mSource(nullptr),
|
||||
mProperty(aProperty),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mTarget(nullptr)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* prop = "(null)";
|
||||
if (aProperty)
|
||||
aProperty->GetValueConst(&prop);
|
||||
|
||||
nsAutoString svar(NS_LITERAL_STRING("(none)"));
|
||||
if (mSourceVariable)
|
||||
mSourceVariable->ToString(svar);
|
||||
|
||||
nsAutoString tvar(NS_LITERAL_STRING("(none)"));
|
||||
if (mTargetVariable)
|
||||
mTargetVariable->ToString(tvar);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
|
||||
this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(tvar).get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsAtom* aTargetVariable)
|
||||
: nsRDFTestNode(aParent),
|
||||
mProcessor(aProcessor),
|
||||
mSourceVariable(nullptr),
|
||||
mSource(aSource),
|
||||
mProperty(aProperty),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mTarget(nullptr)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source = "(null)";
|
||||
if (aSource)
|
||||
aSource->GetValueConst(&source);
|
||||
|
||||
const char* prop = "(null)";
|
||||
if (aProperty)
|
||||
aProperty->GetValueConst(&prop);
|
||||
|
||||
nsAutoString tvar(NS_LITERAL_STRING("(none)"));
|
||||
if (mTargetVariable)
|
||||
mTargetVariable->ToString(tvar);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
|
||||
this, aParent, source, prop, NS_ConvertUTF16toUTF8(tvar).get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsRDFPropertyTestNode::nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aSourceVariable,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
: nsRDFTestNode(aParent),
|
||||
mProcessor(aProcessor),
|
||||
mSourceVariable(aSourceVariable),
|
||||
mSource(nullptr),
|
||||
mProperty(aProperty),
|
||||
mTargetVariable(nullptr),
|
||||
mTarget(aTarget)
|
||||
{
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoString svar(NS_LITERAL_STRING("(none)"));
|
||||
if (mSourceVariable)
|
||||
mSourceVariable->ToString(svar);
|
||||
|
||||
const char* prop = "(null)";
|
||||
if (aProperty)
|
||||
aProperty->GetValueConst(&prop);
|
||||
|
||||
nsAutoString target;
|
||||
nsXULContentUtils::GetTextForNode(aTarget, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: parent=%p source=%s property=%s target=%s",
|
||||
this, aParent, NS_ConvertUTF16toUTF8(svar).get(), prop, NS_ConvertUTF16toUTF8(target).get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsRDFPropertyTestNode::FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aCantHandleYet)
|
||||
*aCantHandleYet = false;
|
||||
|
||||
nsIRDFDataSource* ds = mProcessor->GetDataSource();
|
||||
|
||||
InstantiationSet::Iterator last = aInstantiations.Last();
|
||||
for (InstantiationSet::Iterator inst = aInstantiations.First(); inst != last; ++inst) {
|
||||
bool hasSourceBinding;
|
||||
nsCOMPtr<nsIRDFResource> sourceRes;
|
||||
|
||||
if (mSource) {
|
||||
hasSourceBinding = true;
|
||||
sourceRes = mSource;
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIRDFNode> sourceValue;
|
||||
hasSourceBinding = inst->mAssignments.GetAssignmentFor(mSourceVariable,
|
||||
getter_AddRefs(sourceValue));
|
||||
sourceRes = do_QueryInterface(sourceValue);
|
||||
}
|
||||
|
||||
bool hasTargetBinding;
|
||||
nsCOMPtr<nsIRDFNode> targetValue;
|
||||
|
||||
if (mTarget) {
|
||||
hasTargetBinding = true;
|
||||
targetValue = mTarget;
|
||||
}
|
||||
else {
|
||||
hasTargetBinding = inst->mAssignments.GetAssignmentFor(mTargetVariable,
|
||||
getter_AddRefs(targetValue));
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source = "(unbound)";
|
||||
if (hasSourceBinding)
|
||||
sourceRes->GetValueConst(&source);
|
||||
|
||||
nsAutoString target(NS_LITERAL_STRING("(unbound)"));
|
||||
if (hasTargetBinding)
|
||||
nsXULContentUtils::GetTextForNode(targetValue, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: FilterInstantiations() source=[%s] target=[%s]",
|
||||
this, source, NS_ConvertUTF16toUTF8(target).get()));
|
||||
}
|
||||
|
||||
if (hasSourceBinding && hasTargetBinding) {
|
||||
// it's a consistency check. see if we have a assignment that is consistent
|
||||
bool hasAssertion;
|
||||
rv = ds->HasAssertion(sourceRes, mProperty, targetValue,
|
||||
true, &hasAssertion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" consistency check => %s", hasAssertion ? "passed" : "failed"));
|
||||
|
||||
if (hasAssertion) {
|
||||
// it's consistent.
|
||||
Element* element =
|
||||
new nsRDFPropertyTestNode::Element(sourceRes, mProperty,
|
||||
targetValue);
|
||||
inst->AddSupportingElement(element);
|
||||
}
|
||||
else {
|
||||
// it's inconsistent. remove it.
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
}
|
||||
else if ((hasSourceBinding && ! hasTargetBinding) ||
|
||||
(! hasSourceBinding && hasTargetBinding)) {
|
||||
// it's an open ended query on the source or
|
||||
// target. figure out what matches and add as a
|
||||
// cross-product.
|
||||
nsCOMPtr<nsISimpleEnumerator> results;
|
||||
if (hasSourceBinding) {
|
||||
rv = ds->GetTargets(sourceRes,
|
||||
mProperty,
|
||||
true,
|
||||
getter_AddRefs(results));
|
||||
}
|
||||
else {
|
||||
rv = ds->GetSources(mProperty,
|
||||
targetValue,
|
||||
true,
|
||||
getter_AddRefs(results));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
bool hasMore;
|
||||
rv = results->HasMoreElements(&hasMore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasMore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = results->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAtom* variable;
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
|
||||
if (hasSourceBinding) {
|
||||
variable = mTargetVariable;
|
||||
|
||||
value = do_QueryInterface(isupports);
|
||||
NS_ASSERTION(value != nullptr, "target is not an nsIRDFNode");
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
nsAutoString s(NS_LITERAL_STRING("(none found)"));
|
||||
if (value)
|
||||
nsXULContentUtils::GetTextForNode(value, s);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" target => %s", NS_ConvertUTF16toUTF8(s).get()));
|
||||
}
|
||||
|
||||
if (! value) continue;
|
||||
|
||||
targetValue = value;
|
||||
}
|
||||
else {
|
||||
variable = mSourceVariable;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> source = do_QueryInterface(isupports);
|
||||
NS_ASSERTION(source != nullptr, "source is not an nsIRDFResource");
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* s = "(none found)";
|
||||
if (source)
|
||||
source->GetValueConst(&s);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
(" source => %s", s));
|
||||
}
|
||||
|
||||
if (! source) continue;
|
||||
|
||||
value = sourceRes = source;
|
||||
}
|
||||
|
||||
// Copy the original instantiation, and add it to the
|
||||
// instantiation set with the new assignment that we've
|
||||
// introduced. Ownership will be transferred to the
|
||||
Instantiation newinst = *inst;
|
||||
newinst.AddAssignment(variable, value);
|
||||
|
||||
Element* element =
|
||||
new nsRDFPropertyTestNode::Element(sourceRes, mProperty,
|
||||
targetValue);
|
||||
newinst.AddSupportingElement(element);
|
||||
|
||||
aInstantiations.Insert(inst, newinst);
|
||||
}
|
||||
|
||||
// finally, remove the "under specified" instantiation.
|
||||
aInstantiations.Erase(inst--);
|
||||
}
|
||||
else {
|
||||
if (!aCantHandleYet) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_TRIPLE_UNBOUND);
|
||||
// Neither source nor target assignment!
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
*aCantHandleYet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
nsRDFPropertyTestNode::CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const
|
||||
{
|
||||
bool result;
|
||||
|
||||
if ((mProperty.get() != aProperty) ||
|
||||
(mSource && mSource.get() != aSource) ||
|
||||
(mTarget && mTarget.get() != aTarget)) {
|
||||
result = false;
|
||||
}
|
||||
else {
|
||||
if (mSourceVariable)
|
||||
aInitialBindings.AddAssignment(mSourceVariable, aSource);
|
||||
|
||||
if (mTargetVariable)
|
||||
aInitialBindings.AddAssignment(mTargetVariable, aTarget);
|
||||
|
||||
result = true;
|
||||
}
|
||||
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source;
|
||||
aSource->GetValueConst(&source);
|
||||
|
||||
const char* property;
|
||||
aProperty->GetValueConst(&property);
|
||||
|
||||
nsAutoString target;
|
||||
nsXULContentUtils::GetTextForNode(aTarget, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: CanPropagate([%s]==[%s]=>[%s]) => %s",
|
||||
this, source, property, NS_ConvertUTF16toUTF8(target).get(),
|
||||
result ? "true" : "false"));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsRDFPropertyTestNode::Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const
|
||||
{
|
||||
if (aProperty == mProperty.get()) {
|
||||
if (MOZ_LOG_TEST(gXULTemplateLog, LogLevel::Debug)) {
|
||||
const char* source;
|
||||
aSource->GetValueConst(&source);
|
||||
|
||||
const char* property;
|
||||
aProperty->GetValueConst(&property);
|
||||
|
||||
nsAutoString target;
|
||||
nsXULContentUtils::GetTextForNode(aTarget, target);
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("nsRDFPropertyTestNode[%p]: Retract([%s]==[%s]=>[%s])",
|
||||
this, source, property, NS_ConvertUTF16toUTF8(target).get()));
|
||||
}
|
||||
|
||||
mProcessor->RetractElement(Element(aSource, aProperty, aTarget));
|
||||
}
|
||||
}
|
||||
|
@ -1,104 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFPropertyTestNode_h__
|
||||
#define nsRDFPropertyTestNode_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nscore.h"
|
||||
#include "nsRDFTestNode.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
class nsRDFPropertyTestNode : public nsRDFTestNode
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Both source and target unbound (?source ^property ?target)
|
||||
*/
|
||||
nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aSourceVariable,
|
||||
nsIRDFResource* aProperty,
|
||||
nsAtom* aTargetVariable);
|
||||
|
||||
/**
|
||||
* Source bound, target unbound (source ^property ?target)
|
||||
*/
|
||||
nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsAtom* aTargetVariable);
|
||||
|
||||
/**
|
||||
* Source unbound, target bound (?source ^property target)
|
||||
*/
|
||||
nsRDFPropertyTestNode(TestNode* aParent,
|
||||
nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
nsAtom* aSourceVariable,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const override;
|
||||
|
||||
virtual bool
|
||||
CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const override;
|
||||
|
||||
virtual void
|
||||
Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const override;
|
||||
|
||||
|
||||
class Element : public MemoryElement {
|
||||
public:
|
||||
Element(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
: mSource(aSource),
|
||||
mProperty(aProperty),
|
||||
mTarget(aTarget) {
|
||||
MOZ_COUNT_CTOR(nsRDFPropertyTestNode::Element); }
|
||||
|
||||
virtual ~Element() { MOZ_COUNT_DTOR(nsRDFPropertyTestNode::Element); }
|
||||
|
||||
virtual const char* Type() const override {
|
||||
return "nsRDFPropertyTestNode::Element"; }
|
||||
|
||||
virtual PLHashNumber Hash() const override {
|
||||
return mozilla::HashGeneric(mSource.get(), mProperty.get(), mTarget.get());
|
||||
}
|
||||
|
||||
virtual bool Equals(const MemoryElement& aElement) const override {
|
||||
if (aElement.Type() == Type()) {
|
||||
const Element& element = static_cast<const Element&>(aElement);
|
||||
return mSource == element.mSource
|
||||
&& mProperty == element.mProperty
|
||||
&& mTarget == element.mTarget;
|
||||
}
|
||||
return false; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIRDFResource> mSource;
|
||||
nsCOMPtr<nsIRDFResource> mProperty;
|
||||
nsCOMPtr<nsIRDFNode> mTarget;
|
||||
};
|
||||
|
||||
protected:
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
RefPtr<nsAtom> mSourceVariable;
|
||||
nsCOMPtr<nsIRDFResource> mSource;
|
||||
nsCOMPtr<nsIRDFResource> mProperty;
|
||||
RefPtr<nsAtom> mTargetVariable;
|
||||
nsCOMPtr<nsIRDFNode> mTarget;
|
||||
};
|
||||
|
||||
#endif // nsRDFPropertyTestNode_h__
|
@ -1,47 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
#include "nsRDFQuery.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsRDFQuery, mQueryNode)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsRDFQuery)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITemplateRDFQuery)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsRDFQuery)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsRDFQuery)
|
||||
|
||||
void
|
||||
nsRDFQuery::Finish()
|
||||
{
|
||||
// the template builder is going away and the query processor likely as
|
||||
// well. Clear the reference to avoid calling it.
|
||||
mProcessor = nullptr;
|
||||
mCachedResults = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsRDFQuery::SetCachedResults(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
const InstantiationSet& aInstantiations)
|
||||
{
|
||||
mCachedResults = new nsXULTemplateResultSetRDF(aProcessor, this, &aInstantiations);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsRDFQuery::UseCachedResults(nsISimpleEnumerator** aResults)
|
||||
{
|
||||
*aResults = mCachedResults;
|
||||
NS_IF_ADDREF(*aResults);
|
||||
|
||||
mCachedResults = nullptr;
|
||||
}
|
@ -1,130 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFQuery_h__
|
||||
#define nsRDFQuery_h__
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#define NS_ITEMPLATERDFQUERY_IID \
|
||||
{0x8929ff60, 0x1c9c, 0x4d87, \
|
||||
{ 0xac, 0x02, 0x09, 0x14, 0x15, 0x3b, 0x48, 0xc4 }}
|
||||
|
||||
class nsXULTemplateQueryProcessorRDF;
|
||||
|
||||
/**
|
||||
* A compiled query in the RDF query processor. This interface should not be
|
||||
* used directly outside of the RDF query processor.
|
||||
*/
|
||||
class nsITemplateRDFQuery : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITEMPLATERDFQUERY_IID)
|
||||
|
||||
// return the processor the query was created from
|
||||
virtual nsXULTemplateQueryProcessorRDF* Processor() = 0; // not addrefed
|
||||
|
||||
// return the member variable for the query
|
||||
virtual nsAtom* GetMemberVariable() = 0; // not addrefed
|
||||
|
||||
// return the <query> node the query was compiled from
|
||||
virtual void GetQueryNode(nsIDOMNode** aQueryNode) = 0;
|
||||
|
||||
// remove any results that are cached by the query
|
||||
virtual void ClearCachedResults() = 0;
|
||||
};
|
||||
|
||||
class nsRDFQuery final : public nsITemplateRDFQuery
|
||||
{
|
||||
~nsRDFQuery() { Finish(); }
|
||||
|
||||
public:
|
||||
|
||||
explicit nsRDFQuery(nsXULTemplateQueryProcessorRDF* aProcessor)
|
||||
: mProcessor(aProcessor),
|
||||
mSimple(false),
|
||||
mRoot(nullptr),
|
||||
mCachedResults(nullptr)
|
||||
{ }
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsRDFQuery)
|
||||
|
||||
/**
|
||||
* Retrieve the root node in the rule network
|
||||
* @return the root node in the rule network
|
||||
*/
|
||||
TestNode* GetRoot() { return mRoot; }
|
||||
|
||||
void SetRoot(TestNode* aRoot) { mRoot = aRoot; }
|
||||
|
||||
void GetQueryNode(nsIDOMNode** aQueryNode) override
|
||||
{
|
||||
*aQueryNode = mQueryNode;
|
||||
NS_IF_ADDREF(*aQueryNode);
|
||||
}
|
||||
|
||||
void SetQueryNode(nsIDOMNode* aQueryNode)
|
||||
{
|
||||
mQueryNode = aQueryNode;
|
||||
}
|
||||
|
||||
// an optimization is used when several queries all use the simple query
|
||||
// syntax. Since simple queries can only generate one possible set of
|
||||
// results, they only need to be calculated once and reused for every
|
||||
// simple query. The results may be cached in the query for this purpose.
|
||||
// If successful, this method takes ownership of aInstantiations.
|
||||
nsresult SetCachedResults(nsXULTemplateQueryProcessorRDF* aProcessor,
|
||||
const InstantiationSet& aInstantiations);
|
||||
|
||||
// grab the cached results, if any, causing the caller to take ownership
|
||||
// of them. This also has the effect of setting the cached results in this
|
||||
// nsRDFQuery to null.
|
||||
void UseCachedResults(nsISimpleEnumerator** aResults);
|
||||
|
||||
// clear the cached results
|
||||
void ClearCachedResults() override
|
||||
{
|
||||
mCachedResults = nullptr;
|
||||
}
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* Processor() override { return mProcessor; }
|
||||
|
||||
nsAtom* GetMemberVariable() override { return mMemberVariable; }
|
||||
|
||||
bool IsSimple() { return mSimple; }
|
||||
|
||||
void SetSimple() { mSimple = true; }
|
||||
|
||||
// the reference and member variables for the query
|
||||
RefPtr<nsAtom> mRefVariable;
|
||||
RefPtr<nsAtom> mMemberVariable;
|
||||
|
||||
protected:
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
|
||||
// true if the query is a simple rule (one with a default query)
|
||||
bool mSimple;
|
||||
|
||||
/**
|
||||
* The root node in the network for this query
|
||||
*/
|
||||
TestNode *mRoot;
|
||||
|
||||
// the <query> node
|
||||
nsCOMPtr<nsIDOMNode> mQueryNode;
|
||||
|
||||
// used for simple rules since their results are all determined in one step
|
||||
nsCOMPtr<nsISimpleEnumerator> mCachedResults;
|
||||
|
||||
void Finish();
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsITemplateRDFQuery, NS_ITEMPLATERDFQUERY_IID)
|
||||
|
||||
#endif // nsRDFQuery_h__
|
@ -1,49 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsRDFTestNode_h__
|
||||
#define nsRDFTestNode_h__
|
||||
|
||||
#include "nsRuleNetwork.h"
|
||||
|
||||
class nsIRDFResource;
|
||||
class nsIRDFNode;
|
||||
|
||||
/**
|
||||
* An abstract base class for all of the RDF-related tests. This interface
|
||||
* allows us to iterate over all of the RDF tests to find the one in the
|
||||
* network that is apropos for a newly-added assertion.
|
||||
*/
|
||||
class nsRDFTestNode : public TestNode
|
||||
{
|
||||
public:
|
||||
explicit nsRDFTestNode(TestNode* aParent)
|
||||
: TestNode(aParent) {}
|
||||
|
||||
/**
|
||||
* Determine whether the node can propagate an assertion
|
||||
* with the specified source, property, and target. If the
|
||||
* assertion can be propagated, aInitialBindings will be
|
||||
* initialized with appropriate variable-to-value assignments
|
||||
* to allow the rule network to start a constrain and propagate
|
||||
* search from this node in the network.
|
||||
*
|
||||
* @return true if the node can propagate the specified
|
||||
* assertion.
|
||||
*/
|
||||
virtual bool CanPropagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget,
|
||||
Instantiation& aInitialBindings) const = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget) const = 0;
|
||||
};
|
||||
|
||||
#endif // nsRDFTestNode_h__
|
@ -1,105 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsResourceSet.h"
|
||||
|
||||
nsResourceSet::nsResourceSet(const nsResourceSet& aResourceSet)
|
||||
: mResources(nullptr),
|
||||
mCount(0),
|
||||
mCapacity(0)
|
||||
{
|
||||
ConstIterator last = aResourceSet.Last();
|
||||
for (ConstIterator resource = aResourceSet.First(); resource != last; ++resource)
|
||||
Add(*resource);
|
||||
}
|
||||
|
||||
|
||||
nsResourceSet&
|
||||
nsResourceSet::operator=(const nsResourceSet& aResourceSet)
|
||||
{
|
||||
Clear();
|
||||
ConstIterator last = aResourceSet.Last();
|
||||
for (ConstIterator resource = aResourceSet.First(); resource != last; ++resource)
|
||||
Add(*resource);
|
||||
return *this;
|
||||
}
|
||||
|
||||
nsResourceSet::~nsResourceSet()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsResourceSet);
|
||||
Clear();
|
||||
delete[] mResources;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResourceSet::Clear()
|
||||
{
|
||||
while (--mCount >= 0) {
|
||||
NS_RELEASE(mResources[mCount]);
|
||||
}
|
||||
mCount = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsResourceSet::Add(nsIRDFResource* aResource)
|
||||
{
|
||||
NS_PRECONDITION(aResource != nullptr, "null ptr");
|
||||
if (! aResource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (Contains(aResource))
|
||||
return NS_OK;
|
||||
|
||||
if (mCount >= mCapacity) {
|
||||
int32_t capacity = mCapacity + 4;
|
||||
nsIRDFResource** resources = new nsIRDFResource*[capacity];
|
||||
for (int32_t i = mCount - 1; i >= 0; --i)
|
||||
resources[i] = mResources[i];
|
||||
|
||||
delete[] mResources;
|
||||
|
||||
mResources = resources;
|
||||
mCapacity = capacity;
|
||||
}
|
||||
|
||||
mResources[mCount++] = aResource;
|
||||
NS_ADDREF(aResource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsResourceSet::Remove(nsIRDFResource* aProperty)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
nsIRDFResource** res = mResources;
|
||||
nsIRDFResource** limit = mResources + mCount;
|
||||
while (res < limit) {
|
||||
if (found) {
|
||||
*(res - 1) = *res;
|
||||
}
|
||||
else if (*res == aProperty) {
|
||||
NS_RELEASE(*res);
|
||||
found = true;
|
||||
}
|
||||
++res;
|
||||
}
|
||||
|
||||
if (found)
|
||||
--mCount;
|
||||
}
|
||||
|
||||
bool
|
||||
nsResourceSet::Contains(nsIRDFResource* aResource) const
|
||||
{
|
||||
for (int32_t i = mCount - 1; i >= 0; --i) {
|
||||
if (mResources[i] == aResource)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1,82 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef nsResourceSet_h__
|
||||
#define nsResourceSet_h__
|
||||
|
||||
#include "nsIRDFResource.h"
|
||||
|
||||
class nsResourceSet
|
||||
{
|
||||
public:
|
||||
nsResourceSet()
|
||||
: mResources(nullptr),
|
||||
mCount(0),
|
||||
mCapacity(0) {
|
||||
MOZ_COUNT_CTOR(nsResourceSet); }
|
||||
|
||||
nsResourceSet(const nsResourceSet& aResourceSet);
|
||||
|
||||
nsResourceSet& operator=(const nsResourceSet& aResourceSet);
|
||||
|
||||
~nsResourceSet();
|
||||
|
||||
nsresult Clear();
|
||||
nsresult Add(nsIRDFResource* aProperty);
|
||||
void Remove(nsIRDFResource* aProperty);
|
||||
|
||||
bool Contains(nsIRDFResource* aProperty) const;
|
||||
|
||||
protected:
|
||||
nsIRDFResource** mResources;
|
||||
int32_t mCount;
|
||||
int32_t mCapacity;
|
||||
|
||||
public:
|
||||
class ConstIterator {
|
||||
protected:
|
||||
nsIRDFResource** mCurrent;
|
||||
|
||||
public:
|
||||
ConstIterator() : mCurrent(nullptr) {}
|
||||
|
||||
ConstIterator(const ConstIterator& aConstIterator)
|
||||
: mCurrent(aConstIterator.mCurrent) {}
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& aConstIterator) {
|
||||
mCurrent = aConstIterator.mCurrent;
|
||||
return *this; }
|
||||
|
||||
ConstIterator& operator++() {
|
||||
++mCurrent;
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator++(int) {
|
||||
ConstIterator result(*this);
|
||||
++mCurrent;
|
||||
return result; }
|
||||
|
||||
/*const*/ nsIRDFResource* operator*() const {
|
||||
return *mCurrent; }
|
||||
|
||||
/*const*/ nsIRDFResource* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
|
||||
return *mCurrent; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
|
||||
protected:
|
||||
explicit ConstIterator(nsIRDFResource** aProperty) : mCurrent(aProperty) {}
|
||||
friend class nsResourceSet;
|
||||
};
|
||||
|
||||
ConstIterator First() const { return ConstIterator(mResources); }
|
||||
ConstIterator Last() const { return ConstIterator(mResources + mCount); }
|
||||
};
|
||||
|
||||
#endif // nsResourceSet_h__
|
||||
|
@ -1,428 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
|
||||
Implementations for the rule network classes.
|
||||
|
||||
To Do.
|
||||
|
||||
- Constrain() & Propagate() still feel like they are poorly named.
|
||||
- As do Instantiation and InstantiationSet.
|
||||
- Make InstantiationSet share and do copy-on-write.
|
||||
- Make things iterative, instead of recursive.
|
||||
|
||||
*/
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "plhash.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsXULTemplateResultSetRDF.h"
|
||||
#include "nsRDFConMemberTestNode.h"
|
||||
#include "nsRDFPropertyTestNode.h"
|
||||
|
||||
using namespace mozilla;
|
||||
extern LazyLogModule gXULTemplateLog;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsRuleNetwork
|
||||
//
|
||||
|
||||
nsresult
|
||||
MemoryElementSet::Add(MemoryElement* aElement)
|
||||
{
|
||||
for (ConstIterator element = First(); element != Last(); ++element) {
|
||||
if (*element == *aElement) {
|
||||
// We've already got this element covered. Since Add()
|
||||
// assumes ownership, and we aren't going to need this,
|
||||
// just nuke it.
|
||||
delete aElement;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
List* list = new List;
|
||||
list->mElement = aElement;
|
||||
list->mRefCnt = 1;
|
||||
list->mNext = mElements;
|
||||
|
||||
mElements = list;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsAssignmentSet::Add(const nsAssignment& aAssignment)
|
||||
{
|
||||
NS_PRECONDITION(! HasAssignmentFor(aAssignment.mVariable), "variable already bound");
|
||||
|
||||
// XXXndeakin should this just silently fail?
|
||||
if (HasAssignmentFor(aAssignment.mVariable))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
List* list = new List(aAssignment);
|
||||
list->mRefCnt = 1;
|
||||
list->mNext = mAssignments;
|
||||
|
||||
mAssignments = list;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsAssignmentSet::Count() const
|
||||
{
|
||||
int32_t count = 0;
|
||||
for (ConstIterator assignment = First(); assignment != Last(); ++assignment)
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAssignmentSet::HasAssignment(nsAtom* aVariable, nsIRDFNode* aValue) const
|
||||
{
|
||||
for (ConstIterator assignment = First(); assignment != Last(); ++assignment) {
|
||||
if (assignment->mVariable == aVariable && assignment->mValue == aValue)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAssignmentSet::HasAssignmentFor(nsAtom* aVariable) const
|
||||
{
|
||||
for (ConstIterator assignment = First(); assignment != Last(); ++assignment) {
|
||||
if (assignment->mVariable == aVariable)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAssignmentSet::GetAssignmentFor(nsAtom* aVariable, nsIRDFNode** aValue) const
|
||||
{
|
||||
for (ConstIterator assignment = First(); assignment != Last(); ++assignment) {
|
||||
if (assignment->mVariable == aVariable) {
|
||||
*aValue = assignment->mValue;
|
||||
NS_IF_ADDREF(*aValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*aValue = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsAssignmentSet::Equals(const nsAssignmentSet& aSet) const
|
||||
{
|
||||
if (aSet.mAssignments == mAssignments)
|
||||
return true;
|
||||
|
||||
// If they have a different number of assignments, then they're different.
|
||||
if (Count() != aSet.Count())
|
||||
return false;
|
||||
|
||||
// XXX O(n^2)! Ugh!
|
||||
nsCOMPtr<nsIRDFNode> value;
|
||||
for (ConstIterator assignment = First(); assignment != Last(); ++assignment) {
|
||||
if (! aSet.GetAssignmentFor(assignment->mVariable, getter_AddRefs(value)))
|
||||
return false;
|
||||
|
||||
if (assignment->mValue != value)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
PLHashNumber
|
||||
Instantiation::Hash(const void* aKey)
|
||||
{
|
||||
const Instantiation* inst = static_cast<const Instantiation*>(aKey);
|
||||
|
||||
PLHashNumber result = 0;
|
||||
|
||||
nsAssignmentSet::ConstIterator last = inst->mAssignments.Last();
|
||||
for (nsAssignmentSet::ConstIterator assignment = inst->mAssignments.First();
|
||||
assignment != last; ++assignment)
|
||||
result ^= assignment->Hash();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Instantiation::Compare(const void* aLeft, const void* aRight)
|
||||
{
|
||||
const Instantiation* left = static_cast<const Instantiation*>(aLeft);
|
||||
const Instantiation* right = static_cast<const Instantiation*>(aRight);
|
||||
|
||||
return *left == *right;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// InstantiationSet
|
||||
//
|
||||
|
||||
InstantiationSet::InstantiationSet()
|
||||
{
|
||||
mHead.mPrev = mHead.mNext = &mHead;
|
||||
MOZ_COUNT_CTOR(InstantiationSet);
|
||||
}
|
||||
|
||||
|
||||
InstantiationSet::InstantiationSet(const InstantiationSet& aInstantiationSet)
|
||||
{
|
||||
mHead.mPrev = mHead.mNext = &mHead;
|
||||
|
||||
// XXX replace with copy-on-write foo
|
||||
ConstIterator last = aInstantiationSet.Last();
|
||||
for (ConstIterator inst = aInstantiationSet.First(); inst != last; ++inst)
|
||||
Append(*inst);
|
||||
|
||||
MOZ_COUNT_CTOR(InstantiationSet);
|
||||
}
|
||||
|
||||
InstantiationSet&
|
||||
InstantiationSet::operator=(const InstantiationSet& aInstantiationSet)
|
||||
{
|
||||
// XXX replace with copy-on-write foo
|
||||
Clear();
|
||||
|
||||
ConstIterator last = aInstantiationSet.Last();
|
||||
for (ConstIterator inst = aInstantiationSet.First(); inst != last; ++inst)
|
||||
Append(*inst);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InstantiationSet::Clear()
|
||||
{
|
||||
Iterator inst = First();
|
||||
while (inst != Last())
|
||||
Erase(inst++);
|
||||
}
|
||||
|
||||
|
||||
InstantiationSet::Iterator
|
||||
InstantiationSet::Insert(Iterator aIterator, const Instantiation& aInstantiation)
|
||||
{
|
||||
List* newelement = new List();
|
||||
if (newelement) {
|
||||
newelement->mInstantiation = aInstantiation;
|
||||
|
||||
aIterator.mCurrent->mPrev->mNext = newelement;
|
||||
|
||||
newelement->mNext = aIterator.mCurrent;
|
||||
newelement->mPrev = aIterator.mCurrent->mPrev;
|
||||
|
||||
aIterator.mCurrent->mPrev = newelement;
|
||||
}
|
||||
return aIterator;
|
||||
}
|
||||
|
||||
InstantiationSet::Iterator
|
||||
InstantiationSet::Erase(Iterator aIterator)
|
||||
{
|
||||
Iterator result = aIterator;
|
||||
++result;
|
||||
aIterator.mCurrent->mNext->mPrev = aIterator.mCurrent->mPrev;
|
||||
aIterator.mCurrent->mPrev->mNext = aIterator.mCurrent->mNext;
|
||||
delete aIterator.mCurrent;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
InstantiationSet::HasAssignmentFor(nsAtom* aVariable) const
|
||||
{
|
||||
return !Empty() ? First()->mAssignments.HasAssignmentFor(aVariable) : false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// ReteNode
|
||||
//
|
||||
// The basic node in the network.
|
||||
//
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// TestNode
|
||||
//
|
||||
// to do:
|
||||
// - FilterInstantiations() is poorly named
|
||||
//
|
||||
|
||||
|
||||
TestNode::TestNode(TestNode* aParent)
|
||||
: mParent(aParent)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
TestNode::Propagate(InstantiationSet& aInstantiations,
|
||||
bool aIsUpdate, bool& aTakenInstantiations)
|
||||
{
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Propagate() begin", this));
|
||||
|
||||
aTakenInstantiations = false;
|
||||
|
||||
nsresult rv = FilterInstantiations(aInstantiations, nullptr);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// if there is more than one child, each will need to be supplied with the
|
||||
// original set of instantiations from this node, so create a copy in this
|
||||
// case. If there is only one child, optimize and just pass the
|
||||
// instantiations along to the child without copying
|
||||
bool shouldCopy = (mKids.Count() > 1);
|
||||
|
||||
// See the header file for details about how instantiation ownership works.
|
||||
if (! aInstantiations.Empty()) {
|
||||
ReteNodeSet::Iterator last = mKids.Last();
|
||||
for (ReteNodeSet::Iterator kid = mKids.First(); kid != last; ++kid) {
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Propagate() passing to child %p", this, kid.operator->()));
|
||||
|
||||
// create a copy of the instantiations
|
||||
if (shouldCopy) {
|
||||
bool owned = false;
|
||||
InstantiationSet* instantiations =
|
||||
new InstantiationSet(aInstantiations);
|
||||
rv = kid->Propagate(*instantiations, aIsUpdate, owned);
|
||||
if (!owned)
|
||||
delete instantiations;
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
else {
|
||||
rv = kid->Propagate(aInstantiations, aIsUpdate, aTakenInstantiations);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Propagate() end", this));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
TestNode::Constrain(InstantiationSet& aInstantiations)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Constrain() begin", this));
|
||||
|
||||
// if the cantHandleYet flag is set by FilterInstantiations,
|
||||
// there isn't enough information yet available to fill in.
|
||||
// For this, continue the constrain all the way to the top
|
||||
// and then call FilterInstantiations again afterwards. This
|
||||
// should fill in any missing information.
|
||||
bool cantHandleYet = false;
|
||||
rv = FilterInstantiations(aInstantiations, &cantHandleYet);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (mParent && (!aInstantiations.Empty() || cantHandleYet)) {
|
||||
// if we still have instantiations, or if the instantiations
|
||||
// could not be filled in yet, then ride 'em on up to the
|
||||
// parent to narrow them.
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Constrain() passing to parent %p", this, mParent));
|
||||
|
||||
rv = mParent->Constrain(aInstantiations);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && cantHandleYet)
|
||||
rv = FilterInstantiations(aInstantiations, nullptr);
|
||||
}
|
||||
else {
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Constrain() failed", this));
|
||||
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Debug,
|
||||
("TestNode[%p]: Constrain() end", this));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
ReteNodeSet::ReteNodeSet()
|
||||
: mNodes(nullptr), mCount(0), mCapacity(0)
|
||||
{
|
||||
}
|
||||
|
||||
ReteNodeSet::~ReteNodeSet()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
nsresult
|
||||
ReteNodeSet::Add(ReteNode* aNode)
|
||||
{
|
||||
NS_PRECONDITION(aNode != nullptr, "null ptr");
|
||||
if (! aNode)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (mCount >= mCapacity) {
|
||||
int32_t capacity = mCapacity + 4;
|
||||
ReteNode** nodes = new ReteNode*[capacity];
|
||||
if (! nodes)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
for (int32_t i = mCount - 1; i >= 0; --i)
|
||||
nodes[i] = mNodes[i];
|
||||
|
||||
delete[] mNodes;
|
||||
|
||||
mNodes = nodes;
|
||||
mCapacity = capacity;
|
||||
}
|
||||
|
||||
mNodes[mCount++] = aNode;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ReteNodeSet::Clear()
|
||||
{
|
||||
delete[] mNodes;
|
||||
mNodes = nullptr;
|
||||
mCount = mCapacity = 0;
|
||||
return NS_OK;
|
||||
}
|
@ -1,861 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
|
||||
A rule discrimination network implementation based on ideas from
|
||||
RETE and TREAT.
|
||||
|
||||
RETE is described in Charles Forgy, "Rete: A Fast Algorithm for the
|
||||
Many Patterns/Many Objects Match Problem", Artificial Intelligence
|
||||
19(1): pp. 17-37, 1982.
|
||||
|
||||
TREAT is described in Daniel P. Miranker, "TREAT: A Better Match
|
||||
Algorithm for AI Production System Matching", AAAI 1987: pp. 42-47.
|
||||
|
||||
--
|
||||
|
||||
TO DO:
|
||||
|
||||
. nsAssignmentSet::List objects are allocated by the gallon. We
|
||||
should make it so that these are always allocated from a pool,
|
||||
maybe owned by the nsRuleNetwork?
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsRuleNetwork_h__
|
||||
#define nsRuleNetwork_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "plhash.h"
|
||||
#include "PLDHashTable.h"
|
||||
#include "nsIRDFNode.h"
|
||||
|
||||
class nsXULTemplateResultSetRDF;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A memory element that supports an instantiation. A memory element holds a
|
||||
* set of nodes involved in an RDF test such as <member> or <triple> test. A
|
||||
* memory element is created when a specific test matches. The query processor
|
||||
* maintains a map between the memory elements and the results they eventually
|
||||
* matched. When an assertion is removed from the graph, this map is consulted
|
||||
* to determine which results will no longer match.
|
||||
*/
|
||||
class MemoryElement {
|
||||
protected:
|
||||
MemoryElement() { MOZ_COUNT_CTOR(MemoryElement); }
|
||||
|
||||
public:
|
||||
virtual ~MemoryElement() { MOZ_COUNT_DTOR(MemoryElement); }
|
||||
|
||||
virtual const char* Type() const = 0;
|
||||
virtual PLHashNumber Hash() const = 0;
|
||||
virtual bool Equals(const MemoryElement& aElement) const = 0;
|
||||
|
||||
bool operator==(const MemoryElement& aMemoryElement) const {
|
||||
return Equals(aMemoryElement);
|
||||
}
|
||||
|
||||
bool operator!=(const MemoryElement& aMemoryElement) const {
|
||||
return !Equals(aMemoryElement);
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A collection of memory elements
|
||||
*/
|
||||
class MemoryElementSet {
|
||||
public:
|
||||
class ConstIterator;
|
||||
friend class ConstIterator;
|
||||
|
||||
protected:
|
||||
class List {
|
||||
public:
|
||||
List() { MOZ_COUNT_CTOR(MemoryElementSet::List); }
|
||||
|
||||
protected:
|
||||
~List() {
|
||||
MOZ_COUNT_DTOR(MemoryElementSet::List);
|
||||
delete mElement;
|
||||
NS_IF_RELEASE(mNext); }
|
||||
|
||||
public:
|
||||
int32_t AddRef() { return ++mRefCnt; }
|
||||
|
||||
int32_t Release() {
|
||||
int32_t refcnt = --mRefCnt;
|
||||
if (refcnt == 0) delete this;
|
||||
return refcnt; }
|
||||
|
||||
MemoryElement* mElement;
|
||||
int32_t mRefCnt;
|
||||
List* mNext;
|
||||
};
|
||||
|
||||
List* mElements;
|
||||
|
||||
public:
|
||||
MemoryElementSet() : mElements(nullptr) {
|
||||
MOZ_COUNT_CTOR(MemoryElementSet); }
|
||||
|
||||
MemoryElementSet(const MemoryElementSet& aSet) : mElements(aSet.mElements) {
|
||||
MOZ_COUNT_CTOR(MemoryElementSet);
|
||||
NS_IF_ADDREF(mElements); }
|
||||
|
||||
MemoryElementSet& operator=(const MemoryElementSet& aSet) {
|
||||
NS_IF_RELEASE(mElements);
|
||||
mElements = aSet.mElements;
|
||||
NS_IF_ADDREF(mElements);
|
||||
return *this; }
|
||||
|
||||
~MemoryElementSet() {
|
||||
MOZ_COUNT_DTOR(MemoryElementSet);
|
||||
NS_IF_RELEASE(mElements); }
|
||||
|
||||
public:
|
||||
class ConstIterator {
|
||||
public:
|
||||
explicit ConstIterator(List* aElementList) : mCurrent(aElementList) {
|
||||
NS_IF_ADDREF(mCurrent); }
|
||||
|
||||
ConstIterator(const ConstIterator& aConstIterator)
|
||||
: mCurrent(aConstIterator.mCurrent) {
|
||||
NS_IF_ADDREF(mCurrent); }
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& aConstIterator) {
|
||||
NS_IF_RELEASE(mCurrent);
|
||||
mCurrent = aConstIterator.mCurrent;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return *this; }
|
||||
|
||||
~ConstIterator() { NS_IF_RELEASE(mCurrent); }
|
||||
|
||||
ConstIterator& operator++() {
|
||||
List* next = mCurrent->mNext;
|
||||
NS_RELEASE(mCurrent);
|
||||
mCurrent = next;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator++(int) {
|
||||
ConstIterator result(*this);
|
||||
List* next = mCurrent->mNext;
|
||||
NS_RELEASE(mCurrent);
|
||||
mCurrent = next;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return result; }
|
||||
|
||||
const MemoryElement& operator*() const {
|
||||
return *mCurrent->mElement; }
|
||||
|
||||
const MemoryElement* operator->() const {
|
||||
return mCurrent->mElement; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
|
||||
protected:
|
||||
List* mCurrent;
|
||||
};
|
||||
|
||||
ConstIterator First() const { return ConstIterator(mElements); }
|
||||
ConstIterator Last() const { return ConstIterator(nullptr); }
|
||||
|
||||
// N.B. that the set assumes ownership of the element
|
||||
nsresult Add(MemoryElement* aElement);
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* An assignment of a value to a variable
|
||||
*/
|
||||
class nsAssignment {
|
||||
public:
|
||||
const RefPtr<nsAtom> mVariable;
|
||||
nsCOMPtr<nsIRDFNode> mValue;
|
||||
|
||||
nsAssignment(nsAtom* aVariable, nsIRDFNode* aValue)
|
||||
: mVariable(aVariable),
|
||||
mValue(aValue)
|
||||
{ MOZ_COUNT_CTOR(nsAssignment); }
|
||||
|
||||
nsAssignment(const nsAssignment& aAssignment)
|
||||
: mVariable(aAssignment.mVariable),
|
||||
mValue(aAssignment.mValue)
|
||||
{ MOZ_COUNT_CTOR(nsAssignment); }
|
||||
|
||||
~nsAssignment() { MOZ_COUNT_DTOR(nsAssignment); }
|
||||
|
||||
bool operator==(const nsAssignment& aAssignment) const {
|
||||
return mVariable == aAssignment.mVariable && mValue == aAssignment.mValue; }
|
||||
|
||||
bool operator!=(const nsAssignment& aAssignment) const {
|
||||
return mVariable != aAssignment.mVariable || mValue != aAssignment.mValue; }
|
||||
|
||||
PLHashNumber Hash() const {
|
||||
using mozilla::HashGeneric;
|
||||
return HashGeneric(mVariable.get()) ^ HashGeneric(mValue.get()); }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A collection of value-to-variable assignments that minimizes
|
||||
* copying by sharing subsets when possible.
|
||||
*/
|
||||
class nsAssignmentSet {
|
||||
public:
|
||||
class ConstIterator;
|
||||
friend class ConstIterator;
|
||||
|
||||
protected:
|
||||
class List {
|
||||
public:
|
||||
explicit List(const nsAssignment& aAssignment) : mAssignment(aAssignment) {
|
||||
MOZ_COUNT_CTOR(nsAssignmentSet::List); }
|
||||
|
||||
protected:
|
||||
~List() {
|
||||
MOZ_COUNT_DTOR(nsAssignmentSet::List);
|
||||
NS_IF_RELEASE(mNext); }
|
||||
|
||||
public:
|
||||
|
||||
int32_t AddRef() { return ++mRefCnt; }
|
||||
|
||||
int32_t Release() {
|
||||
int32_t refcnt = --mRefCnt;
|
||||
if (refcnt == 0) delete this;
|
||||
return refcnt; }
|
||||
|
||||
nsAssignment mAssignment;
|
||||
int32_t mRefCnt;
|
||||
List* mNext;
|
||||
};
|
||||
|
||||
List* mAssignments;
|
||||
|
||||
public:
|
||||
nsAssignmentSet()
|
||||
: mAssignments(nullptr)
|
||||
{ MOZ_COUNT_CTOR(nsAssignmentSet); }
|
||||
|
||||
nsAssignmentSet(const nsAssignmentSet& aSet)
|
||||
: mAssignments(aSet.mAssignments) {
|
||||
MOZ_COUNT_CTOR(nsAssignmentSet);
|
||||
NS_IF_ADDREF(mAssignments); }
|
||||
|
||||
nsAssignmentSet& operator=(const nsAssignmentSet& aSet) {
|
||||
NS_IF_RELEASE(mAssignments);
|
||||
mAssignments = aSet.mAssignments;
|
||||
NS_IF_ADDREF(mAssignments);
|
||||
return *this; }
|
||||
|
||||
~nsAssignmentSet() {
|
||||
MOZ_COUNT_DTOR(nsAssignmentSet);
|
||||
NS_IF_RELEASE(mAssignments); }
|
||||
|
||||
public:
|
||||
class ConstIterator {
|
||||
public:
|
||||
explicit ConstIterator(List* aAssignmentList) : mCurrent(aAssignmentList) {
|
||||
NS_IF_ADDREF(mCurrent); }
|
||||
|
||||
ConstIterator(const ConstIterator& aConstIterator)
|
||||
: mCurrent(aConstIterator.mCurrent) {
|
||||
NS_IF_ADDREF(mCurrent); }
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& aConstIterator) {
|
||||
NS_IF_RELEASE(mCurrent);
|
||||
mCurrent = aConstIterator.mCurrent;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return *this; }
|
||||
|
||||
~ConstIterator() { NS_IF_RELEASE(mCurrent); }
|
||||
|
||||
ConstIterator& operator++() {
|
||||
List* next = mCurrent->mNext;
|
||||
NS_RELEASE(mCurrent);
|
||||
mCurrent = next;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator++(int) {
|
||||
ConstIterator result(*this);
|
||||
List* next = mCurrent->mNext;
|
||||
NS_RELEASE(mCurrent);
|
||||
mCurrent = next;
|
||||
NS_IF_ADDREF(mCurrent);
|
||||
return result; }
|
||||
|
||||
const nsAssignment& operator*() const {
|
||||
return mCurrent->mAssignment; }
|
||||
|
||||
const nsAssignment* operator->() const {
|
||||
return &mCurrent->mAssignment; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
|
||||
protected:
|
||||
List* mCurrent;
|
||||
};
|
||||
|
||||
ConstIterator First() const { return ConstIterator(mAssignments); }
|
||||
ConstIterator Last() const { return ConstIterator(nullptr); }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Add an assignment to the set
|
||||
* @param aElement the assigment to add
|
||||
* @return NS_OK if all is well, NS_ERROR_OUT_OF_MEMORY if memory
|
||||
* could not be allocated for the addition.
|
||||
*/
|
||||
nsresult Add(const nsAssignment& aElement);
|
||||
|
||||
/**
|
||||
* Determine if the assignment set contains the specified variable
|
||||
* to value assignment.
|
||||
* @param aVariable the variable for which to lookup the binding
|
||||
* @param aValue the value to query
|
||||
* @return true if aVariable is bound to aValue; false otherwise.
|
||||
*/
|
||||
bool HasAssignment(nsAtom* aVariable, nsIRDFNode* aValue) const;
|
||||
|
||||
/**
|
||||
* Determine if the assignment set contains the specified assignment
|
||||
* @param aAssignment the assignment to search for
|
||||
* @return true if the set contains the assignment, false otherwise.
|
||||
*/
|
||||
bool HasAssignment(const nsAssignment& aAssignment) const {
|
||||
return HasAssignment(aAssignment.mVariable, aAssignment.mValue); }
|
||||
|
||||
/**
|
||||
* Determine whether the assignment set has an assignment for the
|
||||
* specified variable.
|
||||
* @param aVariable the variable to query
|
||||
* @return true if the assignment set has an assignment for the variable,
|
||||
* false otherwise.
|
||||
*/
|
||||
bool HasAssignmentFor(nsAtom* aVariable) const;
|
||||
|
||||
/**
|
||||
* Retrieve the assignment for the specified variable
|
||||
* @param aVariable the variable to query
|
||||
* @param aValue an out parameter that will receive the value assigned
|
||||
* to the variable, if any.
|
||||
* @return true if the variable has an assignment, false
|
||||
* if there was no assignment for the variable.
|
||||
*/
|
||||
bool GetAssignmentFor(nsAtom* aVariable, nsIRDFNode** aValue) const;
|
||||
|
||||
/**
|
||||
* Count the number of assignments in the set
|
||||
* @return the number of assignments in the set
|
||||
*/
|
||||
int32_t Count() const;
|
||||
|
||||
/**
|
||||
* Determine if the set is empty
|
||||
* @return true if the assignment set is empty, false otherwise.
|
||||
*/
|
||||
bool IsEmpty() const { return mAssignments == nullptr; }
|
||||
|
||||
bool Equals(const nsAssignmentSet& aSet) const;
|
||||
bool operator==(const nsAssignmentSet& aSet) const { return Equals(aSet); }
|
||||
bool operator!=(const nsAssignmentSet& aSet) const { return !Equals(aSet); }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A collection of variable-to-value bindings, with the memory elements
|
||||
* that support those bindings. Essentially, an instantiation is the
|
||||
* collection of variables and values assigned to those variables for a single
|
||||
* result. For each RDF rule in the rule network, each instantiation is
|
||||
* examined and either extended with additional bindings specified by the RDF
|
||||
* rule, or removed if the rule doesn't apply (for instance if a node has no
|
||||
* children). When an instantiation gets to the last node of the rule network,
|
||||
* which is always an nsInstantiationNode, a result is created for it.
|
||||
*
|
||||
* An instantiation object is typically created by "extending" another
|
||||
* instantiation object. That is, using the copy constructor, and
|
||||
* adding bindings and support to the instantiation.
|
||||
*/
|
||||
class Instantiation
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* The variable-to-value bindings
|
||||
*/
|
||||
nsAssignmentSet mAssignments;
|
||||
|
||||
/**
|
||||
* The memory elements that support the bindings.
|
||||
*/
|
||||
MemoryElementSet mSupport;
|
||||
|
||||
Instantiation() { MOZ_COUNT_CTOR(Instantiation); }
|
||||
|
||||
Instantiation(const Instantiation& aInstantiation)
|
||||
: mAssignments(aInstantiation.mAssignments),
|
||||
mSupport(aInstantiation.mSupport) {
|
||||
MOZ_COUNT_CTOR(Instantiation); }
|
||||
|
||||
Instantiation& operator=(const Instantiation& aInstantiation) {
|
||||
mAssignments = aInstantiation.mAssignments;
|
||||
mSupport = aInstantiation.mSupport;
|
||||
return *this; }
|
||||
|
||||
~Instantiation() { MOZ_COUNT_DTOR(Instantiation); }
|
||||
|
||||
/**
|
||||
* Add the specified variable-to-value assignment to the instantiation's
|
||||
* set of assignments.
|
||||
* @param aVariable the variable to which is being assigned
|
||||
* @param aValue the value that is being assigned
|
||||
* @return NS_OK if no errors, NS_ERROR_OUT_OF_MEMORY if there
|
||||
* is not enough memory to perform the operation
|
||||
*/
|
||||
nsresult AddAssignment(nsAtom* aVariable, nsIRDFNode* aValue) {
|
||||
mAssignments.Add(nsAssignment(aVariable, aValue));
|
||||
return NS_OK; }
|
||||
|
||||
/**
|
||||
* Add a memory element to the set of memory elements that are
|
||||
* supporting the instantiation
|
||||
* @param aMemoryElement the memory element to add to the
|
||||
* instantiation's set of support
|
||||
* @return NS_OK if no errors occurred, NS_ERROR_OUT_OF_MEMORY
|
||||
* if there is not enough memory to perform the operation.
|
||||
*/
|
||||
nsresult AddSupportingElement(MemoryElement* aMemoryElement) {
|
||||
mSupport.Add(aMemoryElement);
|
||||
return NS_OK; }
|
||||
|
||||
bool Equals(const Instantiation& aInstantiation) const {
|
||||
return mAssignments == aInstantiation.mAssignments; }
|
||||
|
||||
bool operator==(const Instantiation& aInstantiation) const {
|
||||
return Equals(aInstantiation); }
|
||||
|
||||
bool operator!=(const Instantiation& aInstantiation) const {
|
||||
return !Equals(aInstantiation); }
|
||||
|
||||
static PLHashNumber Hash(const void* aKey);
|
||||
static int Compare(const void* aLeft, const void* aRight);
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A collection of intantiations
|
||||
*/
|
||||
class InstantiationSet
|
||||
{
|
||||
public:
|
||||
InstantiationSet();
|
||||
InstantiationSet(const InstantiationSet& aInstantiationSet);
|
||||
InstantiationSet& operator=(const InstantiationSet& aInstantiationSet);
|
||||
|
||||
~InstantiationSet() {
|
||||
MOZ_COUNT_DTOR(InstantiationSet);
|
||||
Clear(); }
|
||||
|
||||
class ConstIterator;
|
||||
friend class ConstIterator;
|
||||
|
||||
class Iterator;
|
||||
friend class Iterator;
|
||||
|
||||
friend class nsXULTemplateResultSetRDF; // so it can get to the List
|
||||
|
||||
protected:
|
||||
class List {
|
||||
public:
|
||||
Instantiation mInstantiation;
|
||||
List* mNext;
|
||||
List* mPrev;
|
||||
|
||||
List() { MOZ_COUNT_CTOR(InstantiationSet::List); }
|
||||
~List() { MOZ_COUNT_DTOR(InstantiationSet::List); }
|
||||
};
|
||||
|
||||
List mHead;
|
||||
|
||||
public:
|
||||
class ConstIterator {
|
||||
protected:
|
||||
friend class Iterator; // XXXwaterson so broken.
|
||||
List* mCurrent;
|
||||
|
||||
public:
|
||||
explicit ConstIterator(List* aList) : mCurrent(aList) {}
|
||||
|
||||
ConstIterator(const ConstIterator& aConstIterator)
|
||||
: mCurrent(aConstIterator.mCurrent) {}
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& aConstIterator) {
|
||||
mCurrent = aConstIterator.mCurrent;
|
||||
return *this; }
|
||||
|
||||
ConstIterator& operator++() {
|
||||
mCurrent = mCurrent->mNext;
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator++(int) {
|
||||
ConstIterator result(*this);
|
||||
mCurrent = mCurrent->mNext;
|
||||
return result; }
|
||||
|
||||
ConstIterator& operator--() {
|
||||
mCurrent = mCurrent->mPrev;
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator--(int) {
|
||||
ConstIterator result(*this);
|
||||
mCurrent = mCurrent->mPrev;
|
||||
return result; }
|
||||
|
||||
const Instantiation& operator*() const {
|
||||
return mCurrent->mInstantiation; }
|
||||
|
||||
const Instantiation* operator->() const {
|
||||
return &mCurrent->mInstantiation; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
};
|
||||
|
||||
ConstIterator First() const { return ConstIterator(mHead.mNext); }
|
||||
ConstIterator Last() const { return ConstIterator(const_cast<List*>(&mHead)); }
|
||||
|
||||
class Iterator : public ConstIterator {
|
||||
public:
|
||||
explicit Iterator(List* aList) : ConstIterator(aList) {}
|
||||
|
||||
Iterator& operator++() {
|
||||
mCurrent = mCurrent->mNext;
|
||||
return *this; }
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator result(*this);
|
||||
mCurrent = mCurrent->mNext;
|
||||
return result; }
|
||||
|
||||
Iterator& operator--() {
|
||||
mCurrent = mCurrent->mPrev;
|
||||
return *this; }
|
||||
|
||||
Iterator operator--(int) {
|
||||
Iterator result(*this);
|
||||
mCurrent = mCurrent->mPrev;
|
||||
return result; }
|
||||
|
||||
Instantiation& operator*() const {
|
||||
return mCurrent->mInstantiation; }
|
||||
|
||||
Instantiation* operator->() const {
|
||||
return &mCurrent->mInstantiation; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
|
||||
friend class InstantiationSet;
|
||||
};
|
||||
|
||||
Iterator First() { return Iterator(mHead.mNext); }
|
||||
Iterator Last() { return Iterator(&mHead); }
|
||||
|
||||
bool Empty() const { return First() == Last(); }
|
||||
|
||||
Iterator Append(const Instantiation& aInstantiation) {
|
||||
return Insert(Last(), aInstantiation); }
|
||||
|
||||
Iterator Insert(Iterator aBefore, const Instantiation& aInstantiation);
|
||||
|
||||
Iterator Erase(Iterator aElement);
|
||||
|
||||
void Clear();
|
||||
|
||||
bool HasAssignmentFor(nsAtom* aVariable) const;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A abstract base class for all nodes in the rule network
|
||||
*/
|
||||
class ReteNode
|
||||
{
|
||||
public:
|
||||
ReteNode() {}
|
||||
virtual ~ReteNode() {}
|
||||
|
||||
/**
|
||||
* Propagate a set of instantiations "down" through the
|
||||
* network. Each instantiation is a partial set of
|
||||
* variable-to-value assignments, along with the memory elements
|
||||
* that support it.
|
||||
*
|
||||
* The node must evaluate each instantiation, and either 1)
|
||||
* extend it with additional assignments and memory-element
|
||||
* support, or 2) remove it from the set because it is
|
||||
* inconsistent with the constraints that this node applies.
|
||||
*
|
||||
* The node must then pass the resulting instantiation set along
|
||||
* to any of its children in the network. (In other words, the
|
||||
* node must recursively call Propagate() on its children. We
|
||||
* should fix this to make the algorithm interruptable.)
|
||||
*
|
||||
* See TestNode::Propagate for details about instantiation set ownership
|
||||
*
|
||||
* @param aInstantiations the set of instantiations to propagate
|
||||
* down through the network.
|
||||
* @param aIsUpdate true if updating, false for first generation
|
||||
* @param aTakenInstantiations true if the ownership over aInstantiations
|
||||
* has been taken from the caller. If false,
|
||||
* the caller owns it.
|
||||
* @return NS_OK if no errors occurred.
|
||||
*/
|
||||
virtual nsresult Propagate(InstantiationSet& aInstantiations,
|
||||
bool aIsUpdate, bool& aTakenInstantiations) = 0;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A collection of nodes in the rule network
|
||||
*/
|
||||
class ReteNodeSet
|
||||
{
|
||||
public:
|
||||
ReteNodeSet();
|
||||
~ReteNodeSet();
|
||||
|
||||
nsresult Add(ReteNode* aNode);
|
||||
nsresult Clear();
|
||||
|
||||
class Iterator;
|
||||
|
||||
class ConstIterator {
|
||||
public:
|
||||
explicit ConstIterator(ReteNode** aNode) : mCurrent(aNode) {}
|
||||
|
||||
ConstIterator(const ConstIterator& aConstIterator)
|
||||
: mCurrent(aConstIterator.mCurrent) {}
|
||||
|
||||
ConstIterator& operator=(const ConstIterator& aConstIterator) {
|
||||
mCurrent = aConstIterator.mCurrent;
|
||||
return *this; }
|
||||
|
||||
ConstIterator& operator++() {
|
||||
++mCurrent;
|
||||
return *this; }
|
||||
|
||||
ConstIterator operator++(int) {
|
||||
ConstIterator result(*this);
|
||||
++mCurrent;
|
||||
return result; }
|
||||
|
||||
const ReteNode* operator*() const {
|
||||
return *mCurrent; }
|
||||
|
||||
const ReteNode* operator->() const {
|
||||
return *mCurrent; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
|
||||
protected:
|
||||
friend class Iterator; // XXXwaterson this is so wrong!
|
||||
ReteNode** mCurrent;
|
||||
};
|
||||
|
||||
ConstIterator First() const { return ConstIterator(mNodes); }
|
||||
ConstIterator Last() const { return ConstIterator(mNodes + mCount); }
|
||||
|
||||
class Iterator : public ConstIterator {
|
||||
public:
|
||||
explicit Iterator(ReteNode** aNode) : ConstIterator(aNode) {}
|
||||
|
||||
Iterator& operator++() {
|
||||
++mCurrent;
|
||||
return *this; }
|
||||
|
||||
Iterator operator++(int) {
|
||||
Iterator result(*this);
|
||||
++mCurrent;
|
||||
return result; }
|
||||
|
||||
ReteNode* operator*() const {
|
||||
return *mCurrent; }
|
||||
|
||||
ReteNode* operator->() const {
|
||||
return *mCurrent; }
|
||||
|
||||
bool operator==(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent == aConstIterator.mCurrent; }
|
||||
|
||||
bool operator!=(const ConstIterator& aConstIterator) const {
|
||||
return mCurrent != aConstIterator.mCurrent; }
|
||||
};
|
||||
|
||||
Iterator First() { return Iterator(mNodes); }
|
||||
Iterator Last() { return Iterator(mNodes + mCount); }
|
||||
|
||||
int32_t Count() const { return mCount; }
|
||||
|
||||
protected:
|
||||
ReteNode** mNodes;
|
||||
int32_t mCount;
|
||||
int32_t mCapacity;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* A node that applies a test condition to a set of instantiations.
|
||||
*
|
||||
* This class provides implementations of Propagate() and Constrain()
|
||||
* in terms of one simple operation, FilterInstantiations(). A node
|
||||
* that is a "simple test node" in a rule network should derive from
|
||||
* this class, and need only implement FilterInstantiations().
|
||||
*/
|
||||
class TestNode : public ReteNode
|
||||
{
|
||||
public:
|
||||
explicit TestNode(TestNode* aParent);
|
||||
|
||||
/**
|
||||
* Retrieve the test node's parent
|
||||
* @return the test node's parent
|
||||
*/
|
||||
TestNode* GetParent() const { return mParent; }
|
||||
|
||||
/**
|
||||
* Calls FilterInstantiations() on the instantiation set, and if
|
||||
* the resulting set isn't empty, propagates the new set down to
|
||||
* each of the test node's children.
|
||||
*
|
||||
* Note that the caller of Propagate is responsible for deleting
|
||||
* aInstantiations if necessary as described below.
|
||||
*
|
||||
* Propagate may be called in update or non-update mode as indicated
|
||||
* by the aIsUpdate argument. Non-update mode is used when initially
|
||||
* generating results, whereas update mode is used when the datasource
|
||||
* changes and new results might be available.
|
||||
*
|
||||
* The last node in a chain of TestNodes is always an nsInstantiationNode.
|
||||
* In non-update mode, this nsInstantiationNode will cache the results
|
||||
* in the query using the SetCachedResults method. The query processor
|
||||
* takes these cached results and creates a nsXULTemplateResultSetRDF
|
||||
* which is the enumeration returned to the template builder. This
|
||||
* nsXULTemplateResultSetRDF owns the instantiations and they will be
|
||||
* deleted when the nsXULTemplateResultSetRDF goes away.
|
||||
*
|
||||
* In update mode, the nsInstantiationNode node will iterate over the
|
||||
* instantiations itself and callback to the builder to update any matches
|
||||
* and generated content. If no instantiations match, then the builder
|
||||
* will never be called.
|
||||
*
|
||||
* Thus, the difference between update and non-update modes is that in
|
||||
* update mode, the results and instantiations have been already handled
|
||||
* whereas in non-update mode they are expected to be returned in an
|
||||
* nsXULTemplateResultSetRDF for further processing by the builder.
|
||||
*
|
||||
* Regardless, aTakenInstantiations will be set to true if the
|
||||
* ownership over aInstantiations has been transferred to a result set.
|
||||
* If set to false, the caller is still responsible for aInstantiations.
|
||||
* aTakenInstantiations will be set properly even if an error occurs.
|
||||
*/
|
||||
virtual nsresult Propagate(InstantiationSet& aInstantiations,
|
||||
bool aIsUpdate, bool& aTakenInstantiations) override;
|
||||
|
||||
/**
|
||||
* This is called by a child node on its parent to allow the
|
||||
* parent's constraints to apply to the set of instantiations.
|
||||
*
|
||||
* A node must iterate through the set of instantiations, and for
|
||||
* each instantiation, either 1) extend the instantiation by
|
||||
* adding variable-to-value assignments and memory element support
|
||||
* for those assignments, or 2) remove the instantiation because
|
||||
* it is inconsistent.
|
||||
*
|
||||
* The node must then pass the resulting set of instantiations up
|
||||
* to its parent (by recursive call; we should make this iterative
|
||||
* & interruptable at some point.)
|
||||
*
|
||||
* @param aInstantiations the set of instantiations that must
|
||||
* be constrained
|
||||
* @return NS_OK if no errors occurred
|
||||
*/
|
||||
virtual nsresult Constrain(InstantiationSet& aInstantiations);
|
||||
|
||||
/**
|
||||
* Given a set of instantiations, filter out any that are
|
||||
* inconsistent with the test node's test, and append
|
||||
* variable-to-value assignments and memory element support for
|
||||
* those which do pass the test node's test.
|
||||
*
|
||||
* @param aInstantiations the set of instantiations to be
|
||||
* filtered
|
||||
* @param aCantHandleYet [out] true if the instantiations do not contain
|
||||
* enough information to constrain the data. May be null if this
|
||||
* isn't important to the caller.
|
||||
* @return NS_OK if no errors occurred.
|
||||
*/
|
||||
virtual nsresult FilterInstantiations(InstantiationSet& aInstantiations,
|
||||
bool* aCantHandleYet) const = 0;
|
||||
//XXX probably better named "ApplyConstraints" or "Discrminiate" or something
|
||||
|
||||
/**
|
||||
* Add another node as a child of this node.
|
||||
* @param aNode the node to add.
|
||||
* @return NS_OK if no errors occur.
|
||||
*/
|
||||
nsresult AddChild(ReteNode* aNode) { return mKids.Add(aNode); }
|
||||
|
||||
/**
|
||||
* Remove all the children of this node
|
||||
* @return NS_OK if no errors occur.
|
||||
*/
|
||||
nsresult RemoveAllChildren() { return mKids.Clear(); }
|
||||
|
||||
protected:
|
||||
TestNode* mParent;
|
||||
ReteNodeSet mKids;
|
||||
};
|
||||
|
||||
#endif // nsRuleNetwork_h__
|
@ -1,64 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsTemplateMap_h__
|
||||
#define nsTemplateMap_h__
|
||||
|
||||
#include "PLDHashTable.h"
|
||||
#include "nsXULElement.h"
|
||||
|
||||
class nsTemplateMap {
|
||||
protected:
|
||||
struct Entry : public PLDHashEntryHdr {
|
||||
nsIContent* mContent;
|
||||
nsIContent* mTemplate;
|
||||
};
|
||||
|
||||
PLDHashTable mTable;
|
||||
|
||||
public:
|
||||
nsTemplateMap() : mTable(PLDHashTable::StubOps(), sizeof(Entry)) { }
|
||||
|
||||
~nsTemplateMap() { }
|
||||
|
||||
void
|
||||
Put(nsIContent* aContent, nsIContent* aTemplate) {
|
||||
NS_ASSERTION(!mTable.Search(aContent), "aContent already in map");
|
||||
|
||||
auto entry = static_cast<Entry*>(mTable.Add(aContent, mozilla::fallible));
|
||||
|
||||
if (entry) {
|
||||
entry->mContent = aContent;
|
||||
entry->mTemplate = aTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Remove(nsIContent* aContent) {
|
||||
mTable.Remove(aContent);
|
||||
|
||||
for (nsIContent* child = aContent->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
Remove(child);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GetTemplateFor(nsIContent* aContent, nsIContent** aResult) {
|
||||
auto entry = static_cast<Entry*>(mTable.Search(aContent));
|
||||
if (entry)
|
||||
NS_IF_ADDREF(*aResult = entry->mTemplate);
|
||||
else
|
||||
*aResult = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Clear() { mTable.Clear(); }
|
||||
};
|
||||
|
||||
#endif // nsTemplateMap_h__
|
||||
|
@ -1,35 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsTemplateMatch.h"
|
||||
#include "nsTemplateRule.h"
|
||||
|
||||
// static
|
||||
void
|
||||
nsTemplateMatch::Destroy(nsTemplateMatch*& aMatch, bool aRemoveResult)
|
||||
{
|
||||
if (aRemoveResult && aMatch->mResult)
|
||||
aMatch->mResult->HasBeenRemoved();
|
||||
::delete aMatch;
|
||||
aMatch = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateMatch::RuleMatched(nsTemplateQuerySet* aQuerySet,
|
||||
nsTemplateRule* aRule,
|
||||
int16_t aRuleIndex,
|
||||
nsIXULTemplateResult* aResult)
|
||||
{
|
||||
// assign the rule index, used to indicate that a match is active, and
|
||||
// so the tree builder can get the right action body to generate
|
||||
mRuleIndex = aRuleIndex;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> rulenode;
|
||||
aRule->GetRuleNode(getter_AddRefs(rulenode));
|
||||
if (rulenode)
|
||||
return aResult->RuleMatched(aQuerySet->mCompiledQuery, rulenode);
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsTemplateMatch_h__
|
||||
#define nsTemplateMatch_h__
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
|
||||
/**
|
||||
* A match object, where each match object is associated with one result.
|
||||
* There will be one match list for each unique id generated. However, since
|
||||
* there are multiple querysets and each may generate results with the same
|
||||
* id, they are all chained together in a linked list, ordered in the same
|
||||
* order as the respective <queryset> elements they were generated from.
|
||||
* A match can be identified by the container and id. The id is retrievable
|
||||
* from the result.
|
||||
*
|
||||
* Only one match per container and id pair is active at a time, but which
|
||||
* match is active may change as new results are added or removed. When a
|
||||
* match is active, content is generated for that match.
|
||||
*
|
||||
* Matches are stored and owned by the mMatchToMap hash in the template
|
||||
* builder.
|
||||
*/
|
||||
|
||||
class nsTemplateRule;
|
||||
class nsTemplateQuerySet;
|
||||
|
||||
class nsTemplateMatch {
|
||||
private:
|
||||
// Hide so that only Create() and Destroy() can be used to
|
||||
// allocate and deallocate from the heap
|
||||
void* operator new(size_t) CPP_THROW_NEW { MOZ_ASSERT(0); return nullptr; }
|
||||
void operator delete(void*, size_t) { MOZ_ASSERT(0); }
|
||||
|
||||
public:
|
||||
nsTemplateMatch(uint16_t aQuerySetPriority,
|
||||
nsIXULTemplateResult* aResult,
|
||||
nsIContent* aContainer)
|
||||
: mRuleIndex(-1),
|
||||
mQuerySetPriority(aQuerySetPriority),
|
||||
mContainer(aContainer),
|
||||
mResult(aResult),
|
||||
mNext(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateMatch);
|
||||
}
|
||||
|
||||
~nsTemplateMatch()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsTemplateMatch);
|
||||
}
|
||||
|
||||
static nsTemplateMatch*
|
||||
Create(uint16_t aQuerySetPriority,
|
||||
nsIXULTemplateResult* aResult,
|
||||
nsIContent* aContainer) {
|
||||
return ::new nsTemplateMatch(aQuerySetPriority, aResult, aContainer);
|
||||
}
|
||||
|
||||
static void Destroy(nsTemplateMatch*& aMatch, bool aRemoveResult);
|
||||
|
||||
// return true if the the match is active, and has generated output
|
||||
bool IsActive() {
|
||||
return mRuleIndex >= 0;
|
||||
}
|
||||
|
||||
// indicate that a rule is no longer active, used when a query with a
|
||||
// lower priority has overriden the match
|
||||
void SetInactive() {
|
||||
mRuleIndex = -1;
|
||||
}
|
||||
|
||||
// return matching rule index
|
||||
int16_t RuleIndex() {
|
||||
return mRuleIndex;
|
||||
}
|
||||
|
||||
// return priority of query set
|
||||
uint16_t QuerySetPriority() {
|
||||
return mQuerySetPriority;
|
||||
}
|
||||
|
||||
// return container, not addrefed. May be null.
|
||||
nsIContent* GetContainer() {
|
||||
return mContainer;
|
||||
}
|
||||
|
||||
nsresult RuleMatched(nsTemplateQuerySet* aQuerySet,
|
||||
nsTemplateRule* aRule,
|
||||
int16_t aRuleIndex,
|
||||
nsIXULTemplateResult* aResult);
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* The index of the rule that matched, or -1 if the match is not active.
|
||||
*/
|
||||
int16_t mRuleIndex;
|
||||
|
||||
/**
|
||||
* The priority of the queryset for this rule
|
||||
*/
|
||||
uint16_t mQuerySetPriority;
|
||||
|
||||
/**
|
||||
* The container the content generated for the match is inside.
|
||||
*/
|
||||
nsCOMPtr<nsIContent> mContainer;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* The result associated with this match
|
||||
*/
|
||||
nsCOMPtr<nsIXULTemplateResult> mResult;
|
||||
|
||||
/**
|
||||
* Matches are stored in a linked list, in priority order. This first
|
||||
* match that has a rule set (mRule) is the active match and generates
|
||||
* content. The next match is owned by the builder, which will delete
|
||||
* template matches when needed.
|
||||
*/
|
||||
nsTemplateMatch *mNext;
|
||||
|
||||
private:
|
||||
|
||||
nsTemplateMatch(const nsTemplateMatch& aMatch) = delete;
|
||||
void operator=(const nsTemplateMatch& aMatch) = delete;
|
||||
};
|
||||
|
||||
#endif // nsTemplateMatch_h__
|
||||
|
@ -1,422 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsTemplateRule.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsICollation.h"
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(nsAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
nsAtom* aTargetVariable,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate)
|
||||
: mSourceVariable(aSourceVariable),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(nsAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
const nsAString& aTargets,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate,
|
||||
bool aIsMultiple)
|
||||
: mSourceVariable(aSourceVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
if (aIsMultiple) {
|
||||
int32_t start = 0, end = 0;
|
||||
while ((end = aTargets.FindChar(',',start)) >= 0) {
|
||||
if (end > start) {
|
||||
mTargetList.AppendElement(Substring(aTargets, start, end - start));
|
||||
}
|
||||
start = end + 1;
|
||||
}
|
||||
if (start < int32_t(aTargets.Length())) {
|
||||
mTargetList.AppendElement(Substring(aTargets, start));
|
||||
}
|
||||
}
|
||||
else {
|
||||
mTargetList.AppendElement(aTargets);
|
||||
}
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
nsTemplateCondition::nsTemplateCondition(const nsAString& aSource,
|
||||
const nsAString& aRelation,
|
||||
nsAtom* aTargetVariable,
|
||||
bool aIgnoreCase,
|
||||
bool aNegate)
|
||||
: mSource(aSource),
|
||||
mTargetVariable(aTargetVariable),
|
||||
mIgnoreCase(aIgnoreCase),
|
||||
mNegate(aNegate),
|
||||
mNext(nullptr)
|
||||
{
|
||||
SetRelation(aRelation);
|
||||
|
||||
MOZ_COUNT_CTOR(nsTemplateCondition);
|
||||
}
|
||||
|
||||
void
|
||||
nsTemplateCondition::SetRelation(const nsAString& aRelation)
|
||||
{
|
||||
if (aRelation.EqualsLiteral("equals") || aRelation.IsEmpty())
|
||||
mRelation = eEquals;
|
||||
else if (aRelation.EqualsLiteral("less"))
|
||||
mRelation = eLess;
|
||||
else if (aRelation.EqualsLiteral("greater"))
|
||||
mRelation = eGreater;
|
||||
else if (aRelation.EqualsLiteral("before"))
|
||||
mRelation = eBefore;
|
||||
else if (aRelation.EqualsLiteral("after"))
|
||||
mRelation = eAfter;
|
||||
else if (aRelation.EqualsLiteral("startswith"))
|
||||
mRelation = eStartswith;
|
||||
else if (aRelation.EqualsLiteral("endswith"))
|
||||
mRelation = eEndswith;
|
||||
else if (aRelation.EqualsLiteral("contains"))
|
||||
mRelation = eContains;
|
||||
else
|
||||
mRelation = eUnknown;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateCondition::CheckMatch(nsIXULTemplateResult* aResult)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
nsAutoString leftString;
|
||||
if (mSourceVariable)
|
||||
aResult->GetBindingFor(mSourceVariable, leftString);
|
||||
else
|
||||
leftString.Assign(mSource);
|
||||
|
||||
if (mTargetVariable) {
|
||||
nsAutoString rightString;
|
||||
aResult->GetBindingFor(mTargetVariable, rightString);
|
||||
|
||||
match = CheckMatchStrings(leftString, rightString);
|
||||
}
|
||||
else {
|
||||
// iterate over the strings in the target and determine
|
||||
// whether there is a match.
|
||||
uint32_t length = mTargetList.Length();
|
||||
for (uint32_t t = 0; t < length; t++) {
|
||||
match = CheckMatchStrings(leftString, mTargetList[t]);
|
||||
|
||||
// stop once a match is found. In negate mode, stop once a
|
||||
// target does not match.
|
||||
if (match != mNegate) break;
|
||||
}
|
||||
}
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsTemplateCondition::CheckMatchStrings(const nsAString& aLeftString,
|
||||
const nsAString& aRightString)
|
||||
{
|
||||
bool match = false;
|
||||
|
||||
if (aRightString.IsEmpty()) {
|
||||
if ((mRelation == eEquals) && aLeftString.IsEmpty())
|
||||
match = true;
|
||||
}
|
||||
else {
|
||||
switch (mRelation) {
|
||||
case eEquals:
|
||||
if (mIgnoreCase)
|
||||
match = aLeftString.Equals(aRightString,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
else
|
||||
match = aLeftString.Equals(aRightString);
|
||||
break;
|
||||
|
||||
case eLess:
|
||||
case eGreater:
|
||||
{
|
||||
// non-numbers always compare false
|
||||
nsresult err;
|
||||
int32_t leftint = PromiseFlatString(aLeftString).ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err)) {
|
||||
int32_t rightint = PromiseFlatString(aRightString).ToInteger(&err);
|
||||
if (NS_SUCCEEDED(err)) {
|
||||
match = (mRelation == eLess) ? (leftint < rightint) :
|
||||
(leftint > rightint);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case eBefore:
|
||||
{
|
||||
nsICollation* collation = nsXULContentUtils::GetCollation();
|
||||
if (collation) {
|
||||
int32_t sortOrder;
|
||||
collation->CompareString((mIgnoreCase ?
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
|
||||
aLeftString,
|
||||
aRightString,
|
||||
&sortOrder);
|
||||
match = (sortOrder < 0);
|
||||
}
|
||||
else if (mIgnoreCase) {
|
||||
match = (Compare(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()) < 0);
|
||||
}
|
||||
else {
|
||||
match = (Compare(aLeftString, aRightString) < 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eAfter:
|
||||
{
|
||||
nsICollation* collation = nsXULContentUtils::GetCollation();
|
||||
if (collation) {
|
||||
int32_t sortOrder;
|
||||
collation->CompareString((mIgnoreCase ?
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseInSensitive) :
|
||||
static_cast<int32_t>(nsICollation::kCollationCaseSensitive)),
|
||||
aLeftString,
|
||||
aRightString,
|
||||
&sortOrder);
|
||||
match = (sortOrder > 0);
|
||||
}
|
||||
else if (mIgnoreCase) {
|
||||
match = (Compare(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()) > 0);
|
||||
}
|
||||
else {
|
||||
match = (Compare(aLeftString, aRightString) > 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case eStartswith:
|
||||
if (mIgnoreCase)
|
||||
match = (StringBeginsWith(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()));
|
||||
else
|
||||
match = (StringBeginsWith(aLeftString, aRightString));
|
||||
break;
|
||||
|
||||
case eEndswith:
|
||||
if (mIgnoreCase)
|
||||
match = (StringEndsWith(aLeftString, aRightString,
|
||||
nsCaseInsensitiveStringComparator()));
|
||||
else
|
||||
match = (StringEndsWith(aLeftString, aRightString));
|
||||
break;
|
||||
|
||||
case eContains:
|
||||
{
|
||||
nsAString::const_iterator start, end;
|
||||
aLeftString.BeginReading(start);
|
||||
aLeftString.EndReading(end);
|
||||
if (mIgnoreCase)
|
||||
match = CaseInsensitiveFindInReadable(aRightString, start, end);
|
||||
else
|
||||
match = FindInReadable(aRightString, start, end);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mNegate) match = !match;
|
||||
|
||||
return match;
|
||||
}
|
||||
|
||||
nsTemplateRule::nsTemplateRule(nsIContent* aRuleNode,
|
||||
nsIContent* aAction,
|
||||
nsTemplateQuerySet* aQuerySet)
|
||||
: mQuerySet(aQuerySet),
|
||||
mAction(aAction),
|
||||
mBindings(nullptr),
|
||||
mConditions(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateRule);
|
||||
mRuleNode = do_QueryInterface(aRuleNode);
|
||||
}
|
||||
|
||||
nsTemplateRule::nsTemplateRule(const nsTemplateRule& aOtherRule)
|
||||
: mQuerySet(aOtherRule.mQuerySet),
|
||||
mRuleNode(aOtherRule.mRuleNode),
|
||||
mAction(aOtherRule.mAction),
|
||||
mBindings(nullptr),
|
||||
mConditions(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateRule);
|
||||
}
|
||||
|
||||
nsTemplateRule::~nsTemplateRule()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsTemplateRule);
|
||||
|
||||
while (mBindings) {
|
||||
Binding* doomed = mBindings;
|
||||
mBindings = mBindings->mNext;
|
||||
delete doomed;
|
||||
}
|
||||
|
||||
while (mConditions) {
|
||||
nsTemplateCondition* cdel = mConditions;
|
||||
mConditions = mConditions->GetNext();
|
||||
delete cdel;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::GetRuleNode(nsIDOMNode** aRuleNode) const
|
||||
{
|
||||
*aRuleNode = mRuleNode;
|
||||
NS_IF_ADDREF(*aRuleNode);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsTemplateRule::SetCondition(nsTemplateCondition* aCondition)
|
||||
{
|
||||
while (mConditions) {
|
||||
nsTemplateCondition* cdel = mConditions;
|
||||
mConditions = mConditions->GetNext();
|
||||
delete cdel;
|
||||
}
|
||||
|
||||
mConditions = aCondition;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateRule::CheckMatch(nsIXULTemplateResult* aResult) const
|
||||
{
|
||||
// check the conditions in the rule first
|
||||
nsTemplateCondition* condition = mConditions;
|
||||
while (condition) {
|
||||
if (!condition->CheckMatch(aResult))
|
||||
return false;
|
||||
|
||||
condition = condition->GetNext();
|
||||
}
|
||||
|
||||
if (mRuleFilter) {
|
||||
// if a rule filter was set, check it for a match. If an error occurs,
|
||||
// assume that the match was acceptable
|
||||
bool match;
|
||||
nsresult rv = mRuleFilter->Match(aResult, mRuleNode, &match);
|
||||
return NS_FAILED(rv) || match;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsTemplateRule::HasBinding(nsAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsAtom* aTargetVariable) const
|
||||
{
|
||||
for (Binding* binding = mBindings; binding != nullptr; binding = binding->mNext) {
|
||||
if ((binding->mSourceVariable == aSourceVariable) &&
|
||||
(binding->mExpr.Equals(aExpr)) &&
|
||||
(binding->mTargetVariable == aTargetVariable))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::AddBinding(nsAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsAtom* aTargetVariable)
|
||||
{
|
||||
NS_PRECONDITION(aSourceVariable != 0, "no source variable!");
|
||||
if (! aSourceVariable)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
NS_PRECONDITION(aTargetVariable != 0, "no target variable!");
|
||||
if (! aTargetVariable)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
NS_ASSERTION(! HasBinding(aSourceVariable, aExpr, aTargetVariable),
|
||||
"binding added twice");
|
||||
|
||||
Binding* newbinding = new Binding;
|
||||
if (! newbinding)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
newbinding->mSourceVariable = aSourceVariable;
|
||||
newbinding->mTargetVariable = aTargetVariable;
|
||||
newbinding->mParent = nullptr;
|
||||
|
||||
newbinding->mExpr.Assign(aExpr);
|
||||
|
||||
Binding* binding = mBindings;
|
||||
Binding** link = &mBindings;
|
||||
|
||||
// Insert it at the end, unless we detect that an existing
|
||||
// binding's source is dependent on the newbinding's target.
|
||||
//
|
||||
// XXXwaterson this isn't enough to make sure that we get all of
|
||||
// the dependencies worked out right, but it'll do for now. For
|
||||
// example, if you have (ab, bc, cd), and insert them in the order
|
||||
// (cd, ab, bc), you'll get (bc, cd, ab). The good news is, if the
|
||||
// person uses a natural ordering when writing the XUL, it'll all
|
||||
// work out ok.
|
||||
while (binding) {
|
||||
if (binding->mSourceVariable == newbinding->mTargetVariable) {
|
||||
binding->mParent = newbinding;
|
||||
break;
|
||||
}
|
||||
else if (binding->mTargetVariable == newbinding->mSourceVariable) {
|
||||
newbinding->mParent = binding;
|
||||
}
|
||||
|
||||
link = &binding->mNext;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
// Insert the newbinding
|
||||
*link = newbinding;
|
||||
newbinding->mNext = binding;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsTemplateRule::AddBindingsToQueryProcessor(nsIXULTemplateQueryProcessor* aProcessor)
|
||||
{
|
||||
Binding* binding = mBindings;
|
||||
|
||||
while (binding) {
|
||||
nsresult rv = aProcessor->AddBinding(mRuleNode, binding->mTargetVariable,
|
||||
binding->mSourceVariable, binding->mExpr);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,328 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsTemplateRule_h__
|
||||
#define nsTemplateRule_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAtom.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIXULTemplateRuleFilter.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsIXULTemplateQueryProcessor;
|
||||
class nsTemplateQuerySet;
|
||||
|
||||
class nsTemplateCondition
|
||||
{
|
||||
public:
|
||||
// relations that may be used in a rule. They may be negated with the
|
||||
// negate flag. Less and Greater are used for numeric comparisons and
|
||||
// Before and After are used for string comparisons. For Less, Greater,
|
||||
// Before, After, Startswith, Endswith, and Contains, the source is
|
||||
// conceptually on the left of the relation and the target is on the
|
||||
// right. For example, if the relation is Contains, that means Match if
|
||||
// the source contains the target.
|
||||
enum ConditionRelation {
|
||||
eUnknown,
|
||||
eEquals,
|
||||
eLess,
|
||||
eGreater,
|
||||
eBefore,
|
||||
eAfter,
|
||||
eStartswith,
|
||||
eEndswith,
|
||||
eContains
|
||||
};
|
||||
|
||||
nsTemplateCondition(nsAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
nsAtom* aTargetVariable,
|
||||
bool mIgnoreCase,
|
||||
bool mNegate);
|
||||
|
||||
nsTemplateCondition(nsAtom* aSourceVariable,
|
||||
const nsAString& aRelation,
|
||||
const nsAString& aTargets,
|
||||
bool mIgnoreCase,
|
||||
bool mNegate,
|
||||
bool aIsMultiple);
|
||||
|
||||
nsTemplateCondition(const nsAString& aSource,
|
||||
const nsAString& aRelation,
|
||||
nsAtom* aTargetVariable,
|
||||
bool mIgnoreCase,
|
||||
bool mNegate);
|
||||
|
||||
~nsTemplateCondition() { MOZ_COUNT_DTOR(nsTemplateCondition); }
|
||||
|
||||
nsTemplateCondition* GetNext() { return mNext; }
|
||||
void SetNext(nsTemplateCondition* aNext) { mNext = aNext; }
|
||||
|
||||
void SetRelation(const nsAString& aRelation);
|
||||
|
||||
bool
|
||||
CheckMatch(nsIXULTemplateResult* aResult);
|
||||
|
||||
bool
|
||||
CheckMatchStrings(const nsAString& aLeftString,
|
||||
const nsAString& aRightString);
|
||||
protected:
|
||||
|
||||
RefPtr<nsAtom> mSourceVariable;
|
||||
nsString mSource;
|
||||
ConditionRelation mRelation;
|
||||
RefPtr<nsAtom> mTargetVariable;
|
||||
nsTArray<nsString> mTargetList;
|
||||
bool mIgnoreCase;
|
||||
bool mNegate;
|
||||
|
||||
nsTemplateCondition* mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* A rule consists of:
|
||||
*
|
||||
* - Conditions, a set of unbound variables with consistency
|
||||
* constraints that specify the values that each variable can
|
||||
* assume. The conditions must be completely and consistently
|
||||
* "bound" for the rule to be considered "matched".
|
||||
*
|
||||
* - Bindings, a set of unbound variables with consistency constraints
|
||||
* that specify the values that each variable can assume. Unlike the
|
||||
* conditions, the bindings need not be bound for the rule to be
|
||||
* considered matched.
|
||||
*
|
||||
* - Content that should be constructed when the rule is "activated".
|
||||
*
|
||||
*/
|
||||
class nsTemplateRule
|
||||
{
|
||||
public:
|
||||
nsTemplateRule(nsIContent* aRuleNode,
|
||||
nsIContent* aAction,
|
||||
nsTemplateQuerySet* aQuerySet);
|
||||
/**
|
||||
* The copy-constructor should only be called from nsTArray when appending
|
||||
* a new rule, otherwise things break because the copy constructor expects
|
||||
* mBindings and mConditions to be nullptr.
|
||||
*/
|
||||
nsTemplateRule(const nsTemplateRule& aOtherRule);
|
||||
|
||||
~nsTemplateRule();
|
||||
|
||||
/**
|
||||
* Return the <action> node that this rule was constructed from, or its
|
||||
* logical equivalent for shorthand syntaxes. That is, the parent node of
|
||||
* the content that should be generated for this rule.
|
||||
*/
|
||||
nsIContent* GetAction() const { return mAction; }
|
||||
|
||||
/**
|
||||
* Return the <rule> content node that this rule was constructed from.
|
||||
* @param aResult an out parameter, which will contain the rule node
|
||||
* @return NS_OK if no errors occur.
|
||||
*/
|
||||
nsresult GetRuleNode(nsIDOMNode** aResult) const;
|
||||
|
||||
void SetVars(nsAtom* aRefVariable, nsAtom* aMemberVariable)
|
||||
{
|
||||
mRefVariable = aRefVariable;
|
||||
mMemberVariable = aMemberVariable;
|
||||
}
|
||||
|
||||
void SetRuleFilter(nsIXULTemplateRuleFilter* aRuleFilter)
|
||||
{
|
||||
mRuleFilter = aRuleFilter;
|
||||
}
|
||||
|
||||
nsAtom* GetTag() { return mTag; }
|
||||
void SetTag(nsAtom* aTag) { mTag = aTag; }
|
||||
|
||||
nsAtom* GetMemberVariable() { return mMemberVariable; }
|
||||
|
||||
/**
|
||||
* Set the first condition for the rule. Other conditions are linked
|
||||
* to it using the condition's SetNext method.
|
||||
*/
|
||||
void SetCondition(nsTemplateCondition* aConditions);
|
||||
|
||||
/**
|
||||
* Check if the result matches the rule by first looking at the conditions.
|
||||
* If the results is accepted by the conditions, the rule filter, if any
|
||||
* was set, is checked. If either check rejects a result, a match cannot
|
||||
* occur for this rule and result.
|
||||
*/
|
||||
bool
|
||||
CheckMatch(nsIXULTemplateResult* aResult) const;
|
||||
|
||||
/**
|
||||
* Determine if the rule has the specified binding
|
||||
*/
|
||||
bool
|
||||
HasBinding(nsAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsAtom* aTargetVariable) const;
|
||||
|
||||
/**
|
||||
* Add a binding to the rule. A binding consists of an already-bound
|
||||
* source variable, and the RDF property that should be tested to
|
||||
* generate a target value. The target value is bound to a target
|
||||
* variable.
|
||||
*
|
||||
* @param aSourceVariable the source variable that will be used in
|
||||
* the RDF query.
|
||||
* @param aExpr the expression that will be used in the query.
|
||||
* @param aTargetVariable the variable whose value will be bound
|
||||
* to the RDF node that is returned when querying the binding
|
||||
* @return NS_OK if no errors occur.
|
||||
*/
|
||||
nsresult AddBinding(nsAtom* aSourceVariable,
|
||||
nsAString& aExpr,
|
||||
nsAtom* aTargetVariable);
|
||||
|
||||
/**
|
||||
* Inform the query processor of the bindings that are set for a rule.
|
||||
* This should be called after all the bindings for a rule are compiled.
|
||||
*/
|
||||
nsresult
|
||||
AddBindingsToQueryProcessor(nsIXULTemplateQueryProcessor* aProcessor);
|
||||
|
||||
void Traverse(nsCycleCollectionTraversalCallback &cb) const
|
||||
{
|
||||
cb.NoteXPCOMChild(mRuleNode);
|
||||
cb.NoteXPCOMChild(mAction);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct Binding {
|
||||
RefPtr<nsAtom> mSourceVariable;
|
||||
RefPtr<nsAtom> mTargetVariable;
|
||||
nsString mExpr;
|
||||
Binding* mNext;
|
||||
Binding* mParent;
|
||||
};
|
||||
|
||||
// backreference to the query set which owns this rule
|
||||
nsTemplateQuerySet* mQuerySet;
|
||||
|
||||
// the <rule> node, or the <template> node if there is no <rule>
|
||||
nsCOMPtr<nsIDOMNode> mRuleNode;
|
||||
|
||||
// the <action> node, or, if there is no <action>, the container node
|
||||
// which contains the content to generate
|
||||
nsCOMPtr<nsIContent> mAction;
|
||||
|
||||
// the rule filter set by the builder's SetRuleFilter function
|
||||
nsCOMPtr<nsIXULTemplateRuleFilter> mRuleFilter;
|
||||
|
||||
// indicates that the rule will only match when generating content
|
||||
// to be inserted into a container with this tag
|
||||
RefPtr<nsAtom> mTag;
|
||||
|
||||
// linked-list of the bindings for the rule, owned by the rule.
|
||||
Binding* mBindings;
|
||||
|
||||
RefPtr<nsAtom> mRefVariable;
|
||||
RefPtr<nsAtom> mMemberVariable;
|
||||
|
||||
nsTemplateCondition* mConditions; // owned by nsTemplateRule
|
||||
};
|
||||
|
||||
/** nsTemplateQuerySet
|
||||
*
|
||||
* A single <queryset> which holds the query node and the rules for it.
|
||||
* All builders have at least one queryset, which may be created with an
|
||||
* explicit <queryset> tag or implied if the tag is not used.
|
||||
*
|
||||
* These queryset objects are created and owned by the builder in its
|
||||
* mQuerySets array.
|
||||
*/
|
||||
class nsTemplateQuerySet
|
||||
{
|
||||
protected:
|
||||
nsTArray<nsTemplateRule> mRules;
|
||||
|
||||
// a number which increments for each successive queryset. It is stored so
|
||||
// it can be used as an optimization when updating results so that it is
|
||||
// known where to insert them into a match.
|
||||
int32_t mPriority;
|
||||
|
||||
public:
|
||||
|
||||
// <query> node
|
||||
nsCOMPtr<nsIContent> mQueryNode;
|
||||
|
||||
// compiled opaque query object returned by the query processor's
|
||||
// CompileQuery call
|
||||
nsCOMPtr<nsISupports> mCompiledQuery;
|
||||
|
||||
// indicates that the query will only generate content to be inserted into
|
||||
// a container with this tag
|
||||
RefPtr<nsAtom> mTag;
|
||||
|
||||
explicit nsTemplateQuerySet(int32_t aPriority)
|
||||
: mPriority(aPriority)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsTemplateQuerySet);
|
||||
}
|
||||
|
||||
~nsTemplateQuerySet()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsTemplateQuerySet);
|
||||
}
|
||||
|
||||
int32_t Priority() const
|
||||
{
|
||||
return mPriority;
|
||||
}
|
||||
|
||||
nsAtom* GetTag() { return mTag; }
|
||||
void SetTag(nsAtom* aTag) { mTag = aTag; }
|
||||
|
||||
nsTemplateRule* NewRule(nsIContent* aRuleNode,
|
||||
nsIContent* aAction,
|
||||
nsTemplateQuerySet* aQuerySet)
|
||||
{
|
||||
// nsTemplateMatch stores the index as a 16-bit value,
|
||||
// so check to make sure for overflow
|
||||
if (mRules.Length() == INT16_MAX)
|
||||
return nullptr;
|
||||
|
||||
return mRules.AppendElement(nsTemplateRule(aRuleNode, aAction,
|
||||
aQuerySet));
|
||||
}
|
||||
|
||||
void RemoveRule(nsTemplateRule *aRule)
|
||||
{
|
||||
mRules.RemoveElementAt(aRule - mRules.Elements());
|
||||
}
|
||||
|
||||
int16_t RuleCount() const
|
||||
{
|
||||
return mRules.Length();
|
||||
}
|
||||
|
||||
nsTemplateRule* GetRuleAt(int16_t aIndex)
|
||||
{
|
||||
if (uint32_t(aIndex) < mRules.Length()) {
|
||||
return &mRules[aIndex];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mRules.Clear();
|
||||
}
|
||||
};
|
||||
|
||||
#endif // nsTemplateRule_h__
|
@ -1,482 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsTreeRows.h"
|
||||
#include <algorithm>
|
||||
|
||||
nsTreeRows::Subtree*
|
||||
nsTreeRows::EnsureSubtreeFor(Subtree* aParent,
|
||||
int32_t aChildIndex)
|
||||
{
|
||||
Subtree* subtree = GetSubtreeFor(aParent, aChildIndex);
|
||||
|
||||
if (! subtree) {
|
||||
subtree = aParent->mRows[aChildIndex].mSubtree = new Subtree(aParent);
|
||||
InvalidateCachedRow();
|
||||
}
|
||||
|
||||
return subtree;
|
||||
}
|
||||
|
||||
nsTreeRows::Subtree*
|
||||
nsTreeRows::GetSubtreeFor(const Subtree* aParent,
|
||||
int32_t aChildIndex,
|
||||
int32_t* aSubtreeSize)
|
||||
{
|
||||
NS_PRECONDITION(aParent, "no parent");
|
||||
NS_PRECONDITION(aChildIndex >= 0, "bad child index");
|
||||
|
||||
Subtree* result = nullptr;
|
||||
|
||||
if (aChildIndex < aParent->mCount)
|
||||
result = aParent->mRows[aChildIndex].mSubtree;
|
||||
|
||||
if (aSubtreeSize)
|
||||
*aSubtreeSize = result ? result->mSubtreeSize : 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::RemoveSubtreeFor(Subtree* aParent, int32_t aChildIndex)
|
||||
{
|
||||
NS_PRECONDITION(aParent, "no parent");
|
||||
NS_PRECONDITION(aChildIndex >= 0 && aChildIndex < aParent->mCount, "bad child index");
|
||||
|
||||
Row& row = aParent->mRows[aChildIndex];
|
||||
|
||||
if (row.mSubtree) {
|
||||
int32_t subtreeSize = row.mSubtree->GetSubtreeSize();
|
||||
|
||||
delete row.mSubtree;
|
||||
row.mSubtree = nullptr;
|
||||
|
||||
for (Subtree* subtree = aParent; subtree != nullptr; subtree = subtree->mParent)
|
||||
subtree->mSubtreeSize -= subtreeSize;
|
||||
}
|
||||
|
||||
InvalidateCachedRow();
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::First()
|
||||
{
|
||||
iterator result;
|
||||
result.Append(&mRoot, 0);
|
||||
result.SetRowIndex(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::Last()
|
||||
{
|
||||
iterator result;
|
||||
|
||||
// Build up a path along the rightmost edge of the tree
|
||||
Subtree* current = &mRoot;
|
||||
int32_t count = current->Count();
|
||||
do {
|
||||
int32_t last = count - 1;
|
||||
result.Append(current, last);
|
||||
current = count ? GetSubtreeFor(current, last) : nullptr;
|
||||
} while (current && ((count = current->Count()) != 0));
|
||||
|
||||
// Now, at the bottom rightmost leaf, advance us one off the end.
|
||||
result.GetTop().mChildIndex++;
|
||||
|
||||
// Our row index will be the size of the root subree, plus one.
|
||||
result.SetRowIndex(mRoot.GetSubtreeSize() + 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::operator[](int32_t aRow)
|
||||
{
|
||||
// See if we're just lucky, and end up with something
|
||||
// nearby. (This tends to happen a lot due to the way that we get
|
||||
// asked for rows n' stuff.)
|
||||
int32_t last = mLastRow.GetRowIndex();
|
||||
if (last != -1) {
|
||||
if (aRow == last)
|
||||
return mLastRow;
|
||||
else if (last + 1 == aRow)
|
||||
return ++mLastRow;
|
||||
else if (last - 1 == aRow)
|
||||
return --mLastRow;
|
||||
}
|
||||
|
||||
// Nope. Construct a path to the specified index. This is a little
|
||||
// bit better than O(n), because we can skip over subtrees. (So it
|
||||
// ends up being approximately linear in the subtree size, instead
|
||||
// of the entire view size. But, most of the time, big views are
|
||||
// flat. Oh well.)
|
||||
iterator result;
|
||||
Subtree* current = &mRoot;
|
||||
|
||||
int32_t index = 0;
|
||||
result.SetRowIndex(aRow);
|
||||
|
||||
do {
|
||||
int32_t subtreeSize;
|
||||
Subtree* subtree = GetSubtreeFor(current, index, &subtreeSize);
|
||||
|
||||
if (subtreeSize >= aRow) {
|
||||
result.Append(current, index);
|
||||
current = subtree;
|
||||
index = 0;
|
||||
--aRow;
|
||||
}
|
||||
else {
|
||||
++index;
|
||||
aRow -= subtreeSize + 1;
|
||||
}
|
||||
} while (aRow >= 0);
|
||||
|
||||
mLastRow = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::FindByResource(nsIRDFResource* aResource)
|
||||
{
|
||||
// XXX Mmm, scan through the rows one-by-one...
|
||||
iterator last = Last();
|
||||
iterator iter;
|
||||
|
||||
nsresult rv;
|
||||
nsAutoString resourceid;
|
||||
bool stringmode = false;
|
||||
|
||||
for (iter = First(); iter != last; ++iter) {
|
||||
if (!stringmode) {
|
||||
nsCOMPtr<nsIRDFResource> findres;
|
||||
rv = iter->mMatch->mResult->GetResource(getter_AddRefs(findres));
|
||||
if (NS_FAILED(rv)) return last;
|
||||
|
||||
if (findres == aResource)
|
||||
break;
|
||||
|
||||
if (! findres) {
|
||||
const char *uri;
|
||||
aResource->GetValueConst(&uri);
|
||||
CopyUTF8toUTF16(uri, resourceid);
|
||||
|
||||
// set stringmode and fall through
|
||||
stringmode = true;
|
||||
}
|
||||
}
|
||||
|
||||
// additional check because previous block could change stringmode
|
||||
if (stringmode) {
|
||||
nsAutoString findid;
|
||||
rv = iter->mMatch->mResult->GetId(findid);
|
||||
if (NS_FAILED(rv)) return last;
|
||||
|
||||
if (resourceid.Equals(findid))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::Find(nsIXULTemplateResult *aResult)
|
||||
{
|
||||
// XXX Mmm, scan through the rows one-by-one...
|
||||
iterator last = Last();
|
||||
iterator iter;
|
||||
|
||||
for (iter = First(); iter != last; ++iter) {
|
||||
if (aResult == iter->mMatch->mResult)
|
||||
break;
|
||||
}
|
||||
|
||||
return iter;
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::Clear()
|
||||
{
|
||||
mRoot.Clear();
|
||||
InvalidateCachedRow();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsTreeRows::Subtree
|
||||
//
|
||||
|
||||
nsTreeRows::Subtree::~Subtree()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::Subtree::Clear()
|
||||
{
|
||||
for (int32_t i = mCount - 1; i >= 0; --i)
|
||||
delete mRows[i].mSubtree;
|
||||
|
||||
delete[] mRows;
|
||||
|
||||
mRows = nullptr;
|
||||
mCount = mCapacity = mSubtreeSize = 0;
|
||||
}
|
||||
|
||||
nsTreeRows::iterator
|
||||
nsTreeRows::Subtree::InsertRowAt(nsTemplateMatch* aMatch, int32_t aIndex)
|
||||
{
|
||||
if (mCount >= mCapacity || aIndex >= mCapacity) {
|
||||
int32_t newCapacity = std::max(mCapacity * 2, aIndex + 1);
|
||||
Row* newRows = new Row[newCapacity];
|
||||
if (! newRows)
|
||||
return iterator();
|
||||
|
||||
for (int32_t i = mCount - 1; i >= 0; --i)
|
||||
newRows[i] = mRows[i];
|
||||
|
||||
delete[] mRows;
|
||||
|
||||
mRows = newRows;
|
||||
mCapacity = newCapacity;
|
||||
}
|
||||
|
||||
for (int32_t i = mCount - 1; i >= aIndex; --i)
|
||||
mRows[i + 1] = mRows[i];
|
||||
|
||||
mRows[aIndex].mMatch = aMatch;
|
||||
mRows[aIndex].mContainerType = eContainerType_Unknown;
|
||||
mRows[aIndex].mContainerState = eContainerState_Unknown;
|
||||
mRows[aIndex].mContainerFill = eContainerFill_Unknown;
|
||||
mRows[aIndex].mSubtree = nullptr;
|
||||
++mCount;
|
||||
|
||||
// Now build an iterator that points to the newly inserted element.
|
||||
int32_t rowIndex = 0;
|
||||
iterator result;
|
||||
result.Push(this, aIndex);
|
||||
|
||||
for ( ; --aIndex >= 0; ++rowIndex) {
|
||||
// Account for open subtrees in the absolute row index.
|
||||
const Subtree *subtree = mRows[aIndex].mSubtree;
|
||||
if (subtree)
|
||||
rowIndex += subtree->mSubtreeSize;
|
||||
}
|
||||
|
||||
Subtree *subtree = this;
|
||||
do {
|
||||
// Note that the subtree's size has expanded.
|
||||
++subtree->mSubtreeSize;
|
||||
|
||||
Subtree *parent = subtree->mParent;
|
||||
if (! parent)
|
||||
break;
|
||||
|
||||
// Account for open subtrees in the absolute row index.
|
||||
int32_t count = parent->Count();
|
||||
for (aIndex = 0; aIndex < count; ++aIndex, ++rowIndex) {
|
||||
const Subtree *child = (*parent)[aIndex].mSubtree;
|
||||
if (subtree == child)
|
||||
break;
|
||||
|
||||
if (child)
|
||||
rowIndex += child->mSubtreeSize;
|
||||
}
|
||||
|
||||
NS_ASSERTION(aIndex < count, "couldn't find subtree in parent");
|
||||
|
||||
result.Push(parent, aIndex);
|
||||
subtree = parent;
|
||||
++rowIndex; // One for the parent row.
|
||||
} while (1);
|
||||
|
||||
result.SetRowIndex(rowIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::Subtree::RemoveRowAt(int32_t aIndex)
|
||||
{
|
||||
NS_PRECONDITION(aIndex >= 0 && aIndex < Count(), "bad index");
|
||||
if (aIndex < 0 || aIndex >= Count())
|
||||
return;
|
||||
|
||||
// How big is the subtree we're going to be removing?
|
||||
int32_t subtreeSize = mRows[aIndex].mSubtree
|
||||
? mRows[aIndex].mSubtree->GetSubtreeSize()
|
||||
: 0;
|
||||
|
||||
++subtreeSize;
|
||||
|
||||
delete mRows[aIndex].mSubtree;
|
||||
|
||||
for (int32_t i = aIndex + 1; i < mCount; ++i)
|
||||
mRows[i - 1] = mRows[i];
|
||||
|
||||
--mCount;
|
||||
|
||||
for (Subtree* subtree = this; subtree != nullptr; subtree = subtree->mParent)
|
||||
subtree->mSubtreeSize -= subtreeSize;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsTreeRows::iterator
|
||||
//
|
||||
|
||||
nsTreeRows::iterator::iterator(const iterator& aIterator)
|
||||
: mRowIndex(aIterator.mRowIndex),
|
||||
mLink(aIterator.mLink)
|
||||
{
|
||||
}
|
||||
|
||||
nsTreeRows::iterator&
|
||||
nsTreeRows::iterator::operator=(const iterator& aIterator)
|
||||
{
|
||||
mRowIndex = aIterator.mRowIndex;
|
||||
mLink = aIterator.mLink;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::iterator::Append(Subtree* aParent, int32_t aChildIndex)
|
||||
{
|
||||
Link *link = mLink.AppendElement();
|
||||
if (link) {
|
||||
link->mParent = aParent;
|
||||
link->mChildIndex = aChildIndex;
|
||||
}
|
||||
else
|
||||
NS_ERROR("out of memory");
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::iterator::Push(Subtree *aParent, int32_t aChildIndex)
|
||||
{
|
||||
Link *link = mLink.InsertElementAt(0);
|
||||
if (link) {
|
||||
link->mParent = aParent;
|
||||
link->mChildIndex = aChildIndex;
|
||||
}
|
||||
else
|
||||
NS_ERROR("out of memory");
|
||||
}
|
||||
|
||||
bool
|
||||
nsTreeRows::iterator::operator==(const iterator& aIterator) const
|
||||
{
|
||||
if (GetDepth() != aIterator.GetDepth())
|
||||
return false;
|
||||
|
||||
if (GetDepth() == 0)
|
||||
return true;
|
||||
|
||||
return GetTop() == aIterator.GetTop();
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::iterator::Next()
|
||||
{
|
||||
NS_PRECONDITION(GetDepth() > 0, "cannot increment an uninitialized iterator");
|
||||
|
||||
// Increment the absolute row index
|
||||
++mRowIndex;
|
||||
|
||||
Link& top = GetTop();
|
||||
|
||||
// Is there a child subtree? If so, descend into the child
|
||||
// subtree.
|
||||
Subtree* subtree = top.GetRow().mSubtree;
|
||||
|
||||
if (subtree && subtree->Count()) {
|
||||
Append(subtree, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Have we exhausted the current subtree?
|
||||
if (top.mChildIndex >= top.mParent->Count() - 1) {
|
||||
// Yep. See if we've just iterated path the last element in
|
||||
// the tree, period. Walk back up the stack, looking for any
|
||||
// unfinished subtrees.
|
||||
int32_t unfinished;
|
||||
for (unfinished = GetDepth() - 2; unfinished >= 0; --unfinished) {
|
||||
const Link& link = mLink[unfinished];
|
||||
if (link.mChildIndex < link.mParent->Count() - 1)
|
||||
break;
|
||||
}
|
||||
|
||||
// If there are no unfinished subtrees in the stack, then this
|
||||
// iterator is exhausted. Leave it in the same state that
|
||||
// Last() does.
|
||||
if (unfinished < 0) {
|
||||
top.mChildIndex++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we ran off the end of one of the inner
|
||||
// subtrees. Pop up to the next unfinished level in the stack.
|
||||
mLink.SetLength(unfinished + 1);
|
||||
}
|
||||
|
||||
// Advance to the next child in this subtree
|
||||
++(GetTop().mChildIndex);
|
||||
}
|
||||
|
||||
void
|
||||
nsTreeRows::iterator::Prev()
|
||||
{
|
||||
NS_PRECONDITION(GetDepth() > 0, "cannot increment an uninitialized iterator");
|
||||
|
||||
// Decrement the absolute row index
|
||||
--mRowIndex;
|
||||
|
||||
// Move to the previous child in this subtree
|
||||
--(GetTop().mChildIndex);
|
||||
|
||||
// Have we exhausted the current subtree?
|
||||
if (GetTop().mChildIndex < 0) {
|
||||
// Yep. See if we've just iterated back to the first element
|
||||
// in the tree, period. Walk back up the stack, looking for
|
||||
// any unfinished subtrees.
|
||||
int32_t unfinished;
|
||||
for (unfinished = GetDepth() - 2; unfinished >= 0; --unfinished) {
|
||||
const Link& link = mLink[unfinished];
|
||||
if (link.mChildIndex >= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
// If there are no unfinished subtrees in the stack, then this
|
||||
// iterator is exhausted. Leave it in the same state that
|
||||
// First() does.
|
||||
if (unfinished < 0)
|
||||
return;
|
||||
|
||||
// Otherwise, we ran off the end of one of the inner
|
||||
// subtrees. Pop up to the next unfinished level in the stack.
|
||||
mLink.SetLength(unfinished + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is there a child subtree immediately prior to our current
|
||||
// position? If so, descend into it, grovelling down to the
|
||||
// deepest, rightmost left edge.
|
||||
Subtree* parent = GetTop().GetParent();
|
||||
int32_t index = GetTop().GetChildIndex();
|
||||
|
||||
Subtree* subtree = (*parent)[index].mSubtree;
|
||||
|
||||
if (subtree && subtree->Count()) {
|
||||
do {
|
||||
index = subtree->Count() - 1;
|
||||
Append(subtree, index);
|
||||
|
||||
parent = subtree;
|
||||
subtree = (*parent)[index].mSubtree;
|
||||
} while (subtree && subtree->Count());
|
||||
}
|
||||
}
|
@ -1,437 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsTreeRows_h__
|
||||
#define nsTreeRows_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "PLDHashTable.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "nsIRDFResource.h"
|
||||
|
||||
class nsTemplateMatch;
|
||||
|
||||
/**
|
||||
* This class maintains the state of the XUL tree builder's
|
||||
* rows. It maps a row number to the nsTemplateMatch object that
|
||||
* populates the row.
|
||||
*/
|
||||
class nsTreeRows
|
||||
{
|
||||
public:
|
||||
class iterator;
|
||||
friend class iterator;
|
||||
|
||||
enum Direction { eDirection_Forwards = +1, eDirection_Backwards = -1 };
|
||||
|
||||
enum ContainerType {
|
||||
eContainerType_Unknown = 0,
|
||||
eContainerType_Noncontainer = 1,
|
||||
eContainerType_Container = 2
|
||||
};
|
||||
|
||||
enum ContainerState {
|
||||
eContainerState_Unknown = 0,
|
||||
eContainerState_Open = 1,
|
||||
eContainerState_Closed = 2
|
||||
};
|
||||
|
||||
enum ContainerFill {
|
||||
eContainerFill_Unknown = 0,
|
||||
eContainerFill_Empty = 1,
|
||||
eContainerFill_Nonempty = 2
|
||||
};
|
||||
|
||||
class Subtree;
|
||||
|
||||
/**
|
||||
* A row in the tree. Contains the match that the row
|
||||
* corresponds to, and a pointer to the row's subtree, if there
|
||||
* are any.
|
||||
*/
|
||||
struct Row {
|
||||
nsTemplateMatch* mMatch;
|
||||
ContainerType mContainerType : 4;
|
||||
ContainerState mContainerState : 4;
|
||||
ContainerFill mContainerFill : 4;
|
||||
|
||||
Subtree* mSubtree; // XXX eventually move to hashtable
|
||||
};
|
||||
|
||||
/**
|
||||
* A subtree in the tree. A subtree contains rows, which may
|
||||
* contain other subtrees.
|
||||
*/
|
||||
class Subtree {
|
||||
protected:
|
||||
friend class nsTreeRows; // so that it can access members, for now
|
||||
|
||||
/**
|
||||
* The parent subtree; null if we're the root
|
||||
*/
|
||||
Subtree* mParent;
|
||||
|
||||
/**
|
||||
* The number of immediate children in this subtree
|
||||
*/
|
||||
int32_t mCount;
|
||||
|
||||
/**
|
||||
* The capacity of the subtree
|
||||
*/
|
||||
int32_t mCapacity;
|
||||
|
||||
/**
|
||||
* The total number of rows in this subtree, recursively
|
||||
* including child subtrees.
|
||||
*/
|
||||
int32_t mSubtreeSize;
|
||||
|
||||
/**
|
||||
* The array of rows in the subtree
|
||||
*/
|
||||
Row* mRows;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates a subtree with the specified parent.
|
||||
*/
|
||||
explicit Subtree(Subtree* aParent)
|
||||
: mParent(aParent),
|
||||
mCount(0),
|
||||
mCapacity(0),
|
||||
mSubtreeSize(0),
|
||||
mRows(nullptr) {}
|
||||
|
||||
~Subtree();
|
||||
|
||||
/**
|
||||
* Return the number of immediate child rows in the subtree
|
||||
*/
|
||||
int32_t Count() const { return mCount; }
|
||||
|
||||
/**
|
||||
* Return the number of rows in this subtree, as well as all
|
||||
* the subtrees it contains.
|
||||
*/
|
||||
int32_t GetSubtreeSize() const { return mSubtreeSize; }
|
||||
|
||||
/**
|
||||
* Retrieve the immediate child row at the specified index.
|
||||
*/
|
||||
const Row& operator[](int32_t aIndex) const {
|
||||
NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
|
||||
return mRows[aIndex]; }
|
||||
|
||||
/**
|
||||
* Retrieve the immediate row at the specified index.
|
||||
*/
|
||||
Row& operator[](int32_t aIndex) {
|
||||
NS_PRECONDITION(aIndex >= 0 && aIndex < mCount, "bad index");
|
||||
return mRows[aIndex]; }
|
||||
|
||||
/**
|
||||
* Remove all rows from the subtree.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Insert an immediate child row at the specified index.
|
||||
*/
|
||||
iterator InsertRowAt(nsTemplateMatch* aMatch, int32_t aIndex);
|
||||
|
||||
/**
|
||||
* Remove an immediate child row from the specified index.
|
||||
*/
|
||||
void RemoveRowAt(int32_t aChildIndex);
|
||||
};
|
||||
|
||||
friend class Subtree;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* A link in the path through the view's tree.
|
||||
*/
|
||||
struct Link {
|
||||
Subtree* mParent;
|
||||
int32_t mChildIndex;
|
||||
|
||||
Link&
|
||||
operator=(const Link& aLink) {
|
||||
mParent = aLink.mParent;
|
||||
mChildIndex = aLink.mChildIndex;
|
||||
return *this; }
|
||||
|
||||
bool
|
||||
operator==(const Link& aLink) const {
|
||||
return (mParent == aLink.mParent)
|
||||
&& (mChildIndex == aLink.mChildIndex); }
|
||||
|
||||
Subtree* GetParent() { return mParent; }
|
||||
const Subtree* GetParent() const { return mParent; }
|
||||
|
||||
int32_t GetChildIndex() const { return mChildIndex; }
|
||||
|
||||
Row& GetRow() { return (*mParent)[mChildIndex]; }
|
||||
const Row& GetRow() const { return (*mParent)[mChildIndex]; }
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* An iterator that can be used to traverse the tree view.
|
||||
*/
|
||||
class iterator {
|
||||
protected:
|
||||
int32_t mRowIndex;
|
||||
AutoTArray<Link, 8> mLink;
|
||||
|
||||
void Next();
|
||||
void Prev();
|
||||
|
||||
friend class Subtree; // so InsertRowAt can initialize us
|
||||
friend class nsTreeRows; // so nsTreeRows can initialize us
|
||||
|
||||
/**
|
||||
* Used by operator[]() to initialize an iterator.
|
||||
*/
|
||||
void Append(Subtree* aParent, int32_t aChildIndex);
|
||||
|
||||
/**
|
||||
* Used by InsertRowAt() to initialize an iterator.
|
||||
*/
|
||||
void Push(Subtree *aParent, int32_t aChildIndex);
|
||||
|
||||
/**
|
||||
* Used by operator[]() and InsertRowAt() to initialize an iterator.
|
||||
*/
|
||||
void SetRowIndex(int32_t aRowIndex) { mRowIndex = aRowIndex; }
|
||||
|
||||
/**
|
||||
* Handy accessors to the top element.
|
||||
*/
|
||||
Link& GetTop() { return mLink[mLink.Length() - 1]; }
|
||||
const Link& GetTop() const { return mLink[mLink.Length() - 1]; }
|
||||
|
||||
public:
|
||||
iterator() : mRowIndex(-1) {}
|
||||
|
||||
iterator(const iterator& aIterator);
|
||||
iterator& operator=(const iterator& aIterator);
|
||||
|
||||
bool operator==(const iterator& aIterator) const;
|
||||
|
||||
bool operator!=(const iterator& aIterator) const {
|
||||
return !aIterator.operator==(*this); }
|
||||
|
||||
const Row& operator*() const { return GetTop().GetRow(); }
|
||||
Row& operator*() { return GetTop().GetRow(); }
|
||||
|
||||
const Row* operator->() const { return &(GetTop().GetRow()); }
|
||||
Row* operator->() { return &(GetTop().GetRow()); }
|
||||
|
||||
iterator& operator++() { Next(); return *this; }
|
||||
iterator operator++(int) { iterator temp(*this); Next(); return temp; }
|
||||
iterator& operator--() { Prev(); return *this; }
|
||||
iterator operator--(int) { iterator temp(*this); Prev(); return temp; }
|
||||
|
||||
/**
|
||||
* Return the current parent link
|
||||
*/
|
||||
Subtree* GetParent() { return GetTop().GetParent(); }
|
||||
|
||||
const Subtree* GetParent() const { return GetTop().GetParent(); }
|
||||
|
||||
/**
|
||||
* Return the current child index
|
||||
*/
|
||||
int32_t GetChildIndex() const { return GetTop().GetChildIndex(); }
|
||||
|
||||
/**
|
||||
* Return the depth of the path the iterator is maintaining
|
||||
* into the tree.
|
||||
*/
|
||||
int32_t GetDepth() const { return mLink.Length(); }
|
||||
|
||||
/**
|
||||
* Return the current row index of the iterator
|
||||
*/
|
||||
int32_t GetRowIndex() const { return mRowIndex; }
|
||||
|
||||
/**
|
||||
* Pop the iterator up a level.
|
||||
*/
|
||||
iterator& Pop() { mLink.SetLength(GetDepth() - 1); return *this; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the first element in the view
|
||||
*/
|
||||
iterator First();
|
||||
|
||||
/**
|
||||
* Retrieve (one past) the last element in the view
|
||||
*/
|
||||
iterator Last();
|
||||
|
||||
/**
|
||||
* Find the row that contains the given resource
|
||||
*/
|
||||
iterator FindByResource(nsIRDFResource* aResource);
|
||||
|
||||
/**
|
||||
* Find the row that contains the result
|
||||
*/
|
||||
iterator Find(nsIXULTemplateResult* aResult);
|
||||
|
||||
/**
|
||||
* Retrieve the ith element in the view
|
||||
*/
|
||||
iterator operator[](int32_t aIndex);
|
||||
|
||||
nsTreeRows() : mRoot(nullptr) {}
|
||||
~nsTreeRows() {}
|
||||
|
||||
/**
|
||||
* Ensure that a child subtree exists within the specified parent
|
||||
* at the specified child index within the parent. (In other
|
||||
* words, create a subtree if one doesn't already exist.)
|
||||
*/
|
||||
Subtree*
|
||||
EnsureSubtreeFor(Subtree* aParent, int32_t aChildIndex);
|
||||
|
||||
/**
|
||||
* Ensure that a child subtree exists at the iterator's position.
|
||||
*/
|
||||
Subtree*
|
||||
EnsureSubtreeFor(iterator& aIterator) {
|
||||
return EnsureSubtreeFor(aIterator.GetParent(),
|
||||
aIterator.GetChildIndex()); }
|
||||
|
||||
/**
|
||||
* Get the child subtree for the specified parent at the specified
|
||||
* child index. Optionally return the child subtree's size. Will
|
||||
* return `null' if no subtree exists.
|
||||
*/
|
||||
Subtree*
|
||||
GetSubtreeFor(const Subtree* aParent,
|
||||
int32_t aChildIndex,
|
||||
int32_t* aSubtreeSize = nullptr);
|
||||
|
||||
/**
|
||||
* Retrieve the size of the subtree within the specified parent.
|
||||
*/
|
||||
int32_t
|
||||
GetSubtreeSizeFor(const Subtree* aParent,
|
||||
int32_t aChildIndex) {
|
||||
int32_t size;
|
||||
GetSubtreeFor(aParent, aChildIndex, &size);
|
||||
return size; }
|
||||
|
||||
/**
|
||||
* Retrieve the size of the subtree within the specified parent.
|
||||
*/
|
||||
int32_t
|
||||
GetSubtreeSizeFor(const iterator& aIterator) {
|
||||
int32_t size;
|
||||
GetSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex(), &size);
|
||||
return size; }
|
||||
|
||||
/**
|
||||
* Remove the specified subtree for a row, leaving the row itself
|
||||
* intact.
|
||||
*/
|
||||
void
|
||||
RemoveSubtreeFor(Subtree* aParent, int32_t aChildIndex);
|
||||
|
||||
/**
|
||||
* Remove the specified subtree for a row, leaving the row itself
|
||||
* intact.
|
||||
*/
|
||||
void
|
||||
RemoveSubtreeFor(iterator& aIterator) {
|
||||
RemoveSubtreeFor(aIterator.GetParent(), aIterator.GetChildIndex()); }
|
||||
|
||||
/**
|
||||
* Remove the specified row from the view
|
||||
*/
|
||||
int32_t
|
||||
RemoveRowAt(iterator& aIterator) {
|
||||
iterator temp = aIterator--;
|
||||
Subtree* parent = temp.GetParent();
|
||||
parent->RemoveRowAt(temp.GetChildIndex());
|
||||
InvalidateCachedRow();
|
||||
return parent->Count(); }
|
||||
|
||||
/**
|
||||
* Insert a new match into the view
|
||||
*/
|
||||
iterator
|
||||
InsertRowAt(nsTemplateMatch* aMatch, Subtree* aSubtree, int32_t aChildIndex) {
|
||||
InvalidateCachedRow();
|
||||
return aSubtree->InsertRowAt(aMatch, aChildIndex); }
|
||||
|
||||
/**
|
||||
* Raw access to the rows; e.g., for sorting.
|
||||
*/
|
||||
Row*
|
||||
GetRowsFor(Subtree* aSubtree) { return aSubtree->mRows; }
|
||||
|
||||
/**
|
||||
* Remove all of the rows
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Return the total number of rows in the tree view.
|
||||
*/
|
||||
int32_t Count() const { return mRoot.GetSubtreeSize(); }
|
||||
|
||||
/**
|
||||
* Retrieve the root subtree
|
||||
*/
|
||||
Subtree* GetRoot() { return &mRoot; }
|
||||
|
||||
/**
|
||||
* Set the root resource for the view
|
||||
*/
|
||||
void SetRootResource(nsIRDFResource* aResource) {
|
||||
mRootResource = aResource; }
|
||||
|
||||
/**
|
||||
* Retrieve the root resource for the view
|
||||
*/
|
||||
nsIRDFResource* GetRootResource() {
|
||||
return mRootResource.get(); }
|
||||
|
||||
/**
|
||||
* Invalidate the cached row; e.g., because the view has changed
|
||||
* in a way that would corrupt the iterator.
|
||||
*/
|
||||
void
|
||||
InvalidateCachedRow() { mLastRow = iterator(); }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The root subtree.
|
||||
*/
|
||||
Subtree mRoot;
|
||||
|
||||
/**
|
||||
* The root resource for the view
|
||||
*/
|
||||
nsCOMPtr<nsIRDFResource> mRootResource;
|
||||
|
||||
/**
|
||||
* The last row that was asked for by operator[]. By remembering
|
||||
* this, we can usually avoid the O(n) search through the row
|
||||
* array to find the row at the specified index.
|
||||
*/
|
||||
iterator mLastRow;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsTreeRows_h__
|
@ -1,118 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
#include "nsXMLBinding.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/XPathResult.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
nsXMLBindingSet::~nsXMLBindingSet()
|
||||
{}
|
||||
|
||||
void
|
||||
nsXMLBindingSet::AddBinding(nsAtom* aVar, nsAutoPtr<XPathExpression>&& aExpr)
|
||||
{
|
||||
nsAutoPtr<nsXMLBinding> newbinding(new nsXMLBinding(aVar, Move(aExpr)));
|
||||
|
||||
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;
|
||||
|
||||
// add the binding at the end of the list
|
||||
if (!binding->mNext) {
|
||||
binding->mNext = newbinding;
|
||||
return;
|
||||
}
|
||||
|
||||
binding = binding->mNext;
|
||||
}
|
||||
}
|
||||
else {
|
||||
mFirst = newbinding;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
nsXMLBindingSet::LookupTargetIndex(nsAtom* aTargetVariable,
|
||||
nsXMLBinding** aBinding)
|
||||
{
|
||||
int32_t idx = 0;
|
||||
nsXMLBinding* binding = mFirst;
|
||||
|
||||
while (binding) {
|
||||
if (binding->mVar == aTargetVariable) {
|
||||
*aBinding = binding;
|
||||
return idx;
|
||||
}
|
||||
idx++;
|
||||
binding = binding->mNext;
|
||||
}
|
||||
|
||||
*aBinding = nullptr;
|
||||
return -1;
|
||||
}
|
||||
|
||||
XPathResult*
|
||||
nsXMLBindingValues::GetAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t aIndex,
|
||||
uint16_t aType)
|
||||
{
|
||||
XPathResult* value = mValues.SafeElementAt(aIndex);
|
||||
if (value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
nsINode* contextNode = aResult->Node();
|
||||
if (!contextNode) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mValues.EnsureLengthAtLeast(aIndex + 1);
|
||||
|
||||
ErrorResult ignored;
|
||||
mValues[aIndex] = aBinding->mExpr->Evaluate(*contextNode, aType, nullptr,
|
||||
ignored);
|
||||
|
||||
return mValues[aIndex];
|
||||
}
|
||||
|
||||
nsINode*
|
||||
nsXMLBindingValues::GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t aIndex)
|
||||
{
|
||||
XPathResult* result = GetAssignmentFor(aResult, aBinding, aIndex,
|
||||
XPathResult::FIRST_ORDERED_NODE_TYPE);
|
||||
|
||||
ErrorResult rv;
|
||||
return result ? result->GetSingleNodeValue(rv) : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsXMLBindingValues::GetStringAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t aIndex,
|
||||
nsAString& aValue)
|
||||
{
|
||||
XPathResult* result = GetAssignmentFor(aResult, aBinding, aIndex,
|
||||
XPathResult::STRING_TYPE);
|
||||
|
||||
if (result) {
|
||||
ErrorResult rv;
|
||||
result->GetStringValue(aValue, rv);
|
||||
} else {
|
||||
aValue.Truncate();
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXMLBinding_h__
|
||||
#define nsXMLBinding_h__
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsAtom.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/XPathExpression.h"
|
||||
|
||||
class nsINode;
|
||||
class nsXULTemplateResultXML;
|
||||
class nsXMLBindingValues;
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class XPathResult;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* Classes related to storing bindings for XML handling.
|
||||
*/
|
||||
|
||||
/**
|
||||
* a <binding> description
|
||||
*/
|
||||
struct nsXMLBinding {
|
||||
RefPtr<nsAtom> mVar;
|
||||
nsAutoPtr<mozilla::dom::XPathExpression> mExpr;
|
||||
|
||||
nsAutoPtr<nsXMLBinding> mNext;
|
||||
|
||||
nsXMLBinding(nsAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr)
|
||||
: mVar(aVar), mExpr(aExpr), mNext(nullptr)
|
||||
{
|
||||
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 final
|
||||
{
|
||||
~nsXMLBindingSet();
|
||||
|
||||
public:
|
||||
// pointer to the first binding in a linked list
|
||||
nsAutoPtr<nsXMLBinding> mFirst;
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(nsXMLBindingSet);
|
||||
|
||||
/**
|
||||
* Add a binding to the set
|
||||
*/
|
||||
void
|
||||
AddBinding(nsAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& 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.
|
||||
*/
|
||||
int32_t
|
||||
LookupTargetIndex(nsAtom* aTargetVariable, nsXMLBinding** aBinding);
|
||||
};
|
||||
|
||||
/**
|
||||
* a set of values of bindings. This object is used once per result.
|
||||
*/
|
||||
class nsXMLBindingValues
|
||||
{
|
||||
protected:
|
||||
|
||||
// the binding set
|
||||
RefPtr<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.
|
||||
*/
|
||||
nsTArray<RefPtr<mozilla::dom::XPathResult> > mValues;
|
||||
|
||||
public:
|
||||
|
||||
nsXMLBindingValues() { MOZ_COUNT_CTOR(nsXMLBindingValues); }
|
||||
~nsXMLBindingValues() { MOZ_COUNT_DTOR(nsXMLBindingValues); }
|
||||
|
||||
nsXMLBindingSet* GetBindingSet() { return mBindings; }
|
||||
|
||||
void SetBindingSet(nsXMLBindingSet* aBindings) { mBindings = aBindings; }
|
||||
|
||||
int32_t
|
||||
LookupTargetIndex(nsAtom* 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
|
||||
*/
|
||||
mozilla::dom::XPathResult*
|
||||
GetAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t idx,
|
||||
uint16_t type);
|
||||
|
||||
nsINode*
|
||||
GetNodeAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t idx);
|
||||
|
||||
void
|
||||
GetStringAssignmentFor(nsXULTemplateResultXML* aResult,
|
||||
nsXMLBinding* aBinding,
|
||||
int32_t idx,
|
||||
nsAString& aValue);
|
||||
};
|
||||
|
||||
#endif // nsXMLBinding_h__
|
File diff suppressed because it is too large
Load Diff
@ -1,327 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
A package of routines shared by the XUL content code.
|
||||
|
||||
*/
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "DateTimeFormat.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMXULCommandDispatcher.h"
|
||||
#include "nsIDOMXULDocument.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsLayoutCID.h"
|
||||
#include "nsNameSpaceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "prtime.h"
|
||||
#include "rdf.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsCollationCID.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nsEscape.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
nsIRDFService* nsXULContentUtils::gRDF;
|
||||
nsICollation *nsXULContentUtils::gCollation;
|
||||
|
||||
extern LazyLogModule gXULTemplateLog;
|
||||
|
||||
#define XUL_RESOURCE(ident, uri) nsIRDFResource* nsXULContentUtils::ident
|
||||
#define XUL_LITERAL(ident, val) nsIRDFLiteral* nsXULContentUtils::ident
|
||||
#include "nsXULResourceList.h"
|
||||
#undef XUL_RESOURCE
|
||||
#undef XUL_LITERAL
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Constructors n' stuff
|
||||
//
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::Init()
|
||||
{
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
nsresult rv = CallGetService(kRDFServiceCID, &gRDF);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
#define XUL_RESOURCE(ident, uri) \
|
||||
PR_BEGIN_MACRO \
|
||||
rv = gRDF->GetResource(NS_LITERAL_CSTRING(uri), &(ident)); \
|
||||
if (NS_FAILED(rv)) return rv; \
|
||||
PR_END_MACRO
|
||||
|
||||
#define XUL_LITERAL(ident, val) \
|
||||
PR_BEGIN_MACRO \
|
||||
rv = gRDF->GetLiteral(val, &(ident)); \
|
||||
if (NS_FAILED(rv)) return rv; \
|
||||
PR_END_MACRO
|
||||
|
||||
#include "nsXULResourceList.h"
|
||||
#undef XUL_RESOURCE
|
||||
#undef XUL_LITERAL
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::Finish()
|
||||
{
|
||||
NS_IF_RELEASE(gRDF);
|
||||
|
||||
#define XUL_RESOURCE(ident, uri) NS_IF_RELEASE(ident)
|
||||
#define XUL_LITERAL(ident, val) NS_IF_RELEASE(ident)
|
||||
#include "nsXULResourceList.h"
|
||||
#undef XUL_RESOURCE
|
||||
#undef XUL_LITERAL
|
||||
|
||||
NS_IF_RELEASE(gCollation);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsICollation*
|
||||
nsXULContentUtils::GetCollation()
|
||||
{
|
||||
if (!gCollation) {
|
||||
nsCOMPtr<nsICollationFactory> colFactory =
|
||||
do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID);
|
||||
if (colFactory) {
|
||||
DebugOnly<nsresult> rv = colFactory->CreateCollation(&gCollation);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv),
|
||||
"couldn't create collation instance");
|
||||
} else
|
||||
NS_ERROR("couldn't create instance of collation factory");
|
||||
}
|
||||
|
||||
return gCollation;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::FindChildByTag(nsIContent* aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsAtom* aTag,
|
||||
Element** aResult)
|
||||
{
|
||||
for (nsIContent* child = aElement->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
|
||||
if (child->IsElement() &&
|
||||
child->NodeInfo()->Equals(aTag, aNameSpaceID)) {
|
||||
NS_ADDREF(*aResult = child->AsElement());
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
return NS_RDF_NO_VALUE; // not found
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode
|
||||
*/
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::GetTextForNode(nsIRDFNode* aNode, nsAString& aResult)
|
||||
{
|
||||
if (! aNode) {
|
||||
aResult.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Literals are the most common, so try these first.
|
||||
nsCOMPtr<nsIRDFLiteral> literal = do_QueryInterface(aNode);
|
||||
if (literal) {
|
||||
const char16_t* p;
|
||||
rv = literal->GetValueConst(&p);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
aResult = p;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFDate> dateLiteral = do_QueryInterface(aNode);
|
||||
if (dateLiteral) {
|
||||
PRTime value;
|
||||
rv = dateLiteral->GetValue(&value);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString str;
|
||||
rv = DateTimeFormat::FormatPRTime(kDateFormatShort,
|
||||
kTimeFormatSeconds,
|
||||
value,
|
||||
str);
|
||||
|
||||
aResult.Assign(str);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFInt> intLiteral = do_QueryInterface(aNode);
|
||||
if (intLiteral) {
|
||||
int32_t value;
|
||||
rv = intLiteral->GetValue(&value);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
aResult.Truncate();
|
||||
nsAutoString intStr;
|
||||
intStr.AppendInt(value, 10);
|
||||
aResult.Append(intStr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsCOMPtr<nsIRDFResource> resource = do_QueryInterface(aNode);
|
||||
if (resource) {
|
||||
const char* p;
|
||||
rv = resource->GetValueConst(&p);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
CopyUTF8toUTF16(p, aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ERROR("not a resource or a literal");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::GetResource(int32_t aNameSpaceID, nsAtom* aAttribute, nsIRDFResource** aResult)
|
||||
{
|
||||
// construct a fully-qualified URI from the namespace/tag pair.
|
||||
NS_PRECONDITION(aAttribute != nullptr, "null ptr");
|
||||
if (! aAttribute)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
return GetResource(aNameSpaceID, nsDependentAtomString(aAttribute),
|
||||
aResult);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::GetResource(int32_t aNameSpaceID, const nsAString& aAttribute, nsIRDFResource** aResult)
|
||||
{
|
||||
// construct a fully-qualified URI from the namespace/tag pair.
|
||||
|
||||
// XXX should we allow nodes with no namespace???
|
||||
//NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "no namespace");
|
||||
//if (aNameSpaceID == kNameSpaceID_Unknown)
|
||||
// return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsAutoStringN<256> uri;
|
||||
if (aNameSpaceID != kNameSpaceID_Unknown && aNameSpaceID != kNameSpaceID_None) {
|
||||
rv = nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, uri);
|
||||
// XXX ignore failure; treat as "no namespace"
|
||||
}
|
||||
|
||||
// XXX check to see if we need to insert a '/' or a '#'. Oy.
|
||||
if (!uri.IsEmpty() && uri.Last() != '#' && uri.Last() != '/' && aAttribute.First() != '#')
|
||||
uri.Append(char16_t('#'));
|
||||
|
||||
uri.Append(aAttribute);
|
||||
|
||||
rv = gRDF->GetUnicodeResource(uri, aResult);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get resource");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, Element* aElement)
|
||||
{
|
||||
// Deal with setting up a 'commandupdater'. Pulls the 'events' and
|
||||
// 'targets' attributes off of aElement, and adds it to the
|
||||
// document's command dispatcher.
|
||||
NS_PRECONDITION(aDocument != nullptr, "null ptr");
|
||||
if (! aDocument)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aElement != nullptr, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDOMXULDocument> xuldoc = do_QueryInterface(aDocument);
|
||||
NS_ASSERTION(xuldoc != nullptr, "not a xul document");
|
||||
if (! xuldoc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher;
|
||||
rv = xuldoc->GetCommandDispatcher(getter_AddRefs(dispatcher));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get dispatcher");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(dispatcher != nullptr, "no dispatcher");
|
||||
if (! dispatcher)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsAutoString events;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events);
|
||||
if (events.IsEmpty())
|
||||
events.Assign('*');
|
||||
|
||||
nsAutoString targets;
|
||||
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::targets, targets);
|
||||
|
||||
if (targets.IsEmpty())
|
||||
targets.Assign('*');
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domelement = do_QueryInterface(aElement);
|
||||
NS_ASSERTION(domelement != nullptr, "not a DOM element");
|
||||
if (! domelement)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = dispatcher->AddCommandUpdater(domelement, events, targets);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULContentUtils::LogTemplateError(const char* aStr)
|
||||
{
|
||||
nsAutoString message;
|
||||
message.AssignLiteral("Error parsing template: ");
|
||||
message.Append(NS_ConvertUTF8toUTF16(aStr).get());
|
||||
|
||||
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (cs) {
|
||||
cs->LogStringMessage(message.get());
|
||||
MOZ_LOG(gXULTemplateLog, LogLevel::Info, ("Error parsing template: %s", aStr));
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
|
||||
A package of routines shared by the XUL content code.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef nsXULContentUtils_h__
|
||||
#define nsXULContentUtils_h__
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
||||
class nsAtom;
|
||||
class nsIContent;
|
||||
class nsIDocument;
|
||||
class nsIRDFNode;
|
||||
class nsIRDFResource;
|
||||
class nsIRDFLiteral;
|
||||
class nsIRDFService;
|
||||
class nsICollation;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
|
||||
// errors to pass to LogTemplateError
|
||||
#define ERROR_TEMPLATE_INVALID_QUERYPROCESSOR \
|
||||
"querytype attribute doesn't specify a valid query processor"
|
||||
#define ERROR_TEMPLATE_INVALID_QUERYSET \
|
||||
"unexpected <queryset> element"
|
||||
#define ERROR_TEMPLATE_NO_MEMBERVAR \
|
||||
"no member variable found. Action body should have an element with uri attribute"
|
||||
#define ERROR_TEMPLATE_WHERE_NO_SUBJECT \
|
||||
"<where> element is missing a subject attribute"
|
||||
#define ERROR_TEMPLATE_WHERE_NO_RELATION \
|
||||
"<where> element is missing a rel attribute"
|
||||
#define ERROR_TEMPLATE_WHERE_NO_VALUE \
|
||||
"<where> element is missing a value attribute"
|
||||
#define ERROR_TEMPLATE_WHERE_NO_VAR \
|
||||
"<where> element must have at least one variable as a subject or value"
|
||||
#define ERROR_TEMPLATE_BINDING_BAD_SUBJECT \
|
||||
"<binding> requires a variable for its subject attribute"
|
||||
#define ERROR_TEMPLATE_BINDING_BAD_PREDICATE \
|
||||
"<binding> element is missing a predicate attribute"
|
||||
#define ERROR_TEMPLATE_BINDING_BAD_OBJECT \
|
||||
"<binding> requires a variable for its object attribute"
|
||||
#define ERROR_TEMPLATE_CONTENT_NOT_FIRST \
|
||||
"expected <content> to be first"
|
||||
#define ERROR_TEMPLATE_MEMBER_NOCONTAINERVAR \
|
||||
"<member> requires a variable for its container attribute"
|
||||
#define ERROR_TEMPLATE_MEMBER_NOCHILDVAR \
|
||||
"<member> requires a variable for its child attribute"
|
||||
#define ERROR_TEMPLATE_TRIPLE_NO_VAR \
|
||||
"<triple> should have at least one variable as a subject or object"
|
||||
#define ERROR_TEMPLATE_TRIPLE_BAD_SUBJECT \
|
||||
"<triple> requires a variable for its subject attribute"
|
||||
#define ERROR_TEMPLATE_TRIPLE_BAD_PREDICATE \
|
||||
"<triple> should have a non-variable value as a predicate"
|
||||
#define ERROR_TEMPLATE_TRIPLE_BAD_OBJECT \
|
||||
"<triple> requires a variable for its object attribute"
|
||||
#define ERROR_TEMPLATE_MEMBER_UNBOUND \
|
||||
"neither container or child variables of <member> has a value"
|
||||
#define ERROR_TEMPLATE_TRIPLE_UNBOUND \
|
||||
"neither subject or object variables of <triple> has a value"
|
||||
#define ERROR_TEMPLATE_BAD_XPATH \
|
||||
"XPath expression in query could not be parsed"
|
||||
#define ERROR_TEMPLATE_BAD_ASSIGN_XPATH \
|
||||
"XPath expression in <assign> could not be parsed"
|
||||
#define ERROR_TEMPLATE_BAD_BINDING_XPATH \
|
||||
"XPath expression in <binding> could not be parsed"
|
||||
#define ERROR_TEMPLATE_STORAGE_BAD_URI \
|
||||
"only profile: or file URI are allowed"
|
||||
#define ERROR_TEMPLATE_STORAGE_CANNOT_OPEN_DATABASE \
|
||||
"cannot open given database"
|
||||
#define ERROR_TEMPLATE_STORAGE_BAD_QUERY \
|
||||
"syntax error in the SQL query"
|
||||
#define ERROR_TEMPLATE_STORAGE_UNKNOWN_QUERY_PARAMETER \
|
||||
"the given named parameter is unknown in the SQL query"
|
||||
#define ERROR_TEMPLATE_STORAGE_WRONG_TYPE_QUERY_PARAMETER \
|
||||
"the type of a query parameter is wrong"
|
||||
#define ERROR_TEMPLATE_STORAGE_QUERY_PARAMETER_NOT_BOUND \
|
||||
"a query parameter cannot be bound to the SQL query"
|
||||
|
||||
class nsXULContentUtils
|
||||
{
|
||||
protected:
|
||||
static nsIRDFService* gRDF;
|
||||
static nsICollation *gCollation;
|
||||
|
||||
static bool gDisableXULCache;
|
||||
|
||||
static int
|
||||
DisableXULCacheChangedCallback(const char* aPrefName, void* aClosure);
|
||||
|
||||
public:
|
||||
static nsresult
|
||||
Init();
|
||||
|
||||
static nsresult
|
||||
Finish();
|
||||
|
||||
static nsresult
|
||||
FindChildByTag(nsIContent *aElement,
|
||||
int32_t aNameSpaceID,
|
||||
nsAtom* aTag,
|
||||
mozilla::dom::Element** aResult);
|
||||
|
||||
static nsresult
|
||||
FindChildByResource(nsIContent* aElement,
|
||||
nsIRDFResource* aResource,
|
||||
nsIContent** aResult);
|
||||
|
||||
static nsresult
|
||||
GetTextForNode(nsIRDFNode* aNode, nsAString& aResult);
|
||||
|
||||
static nsresult
|
||||
GetResource(int32_t aNameSpaceID, nsAtom* aAttribute, nsIRDFResource** aResult);
|
||||
|
||||
static nsresult
|
||||
GetResource(int32_t aNameSpaceID, const nsAString& aAttribute, nsIRDFResource** aResult);
|
||||
|
||||
static nsresult
|
||||
SetCommandUpdater(nsIDocument* aDocument, mozilla::dom::Element* aElement);
|
||||
|
||||
/**
|
||||
* Log a message to the error console
|
||||
*/
|
||||
static void
|
||||
LogTemplateError(const char* aMsg);
|
||||
|
||||
static nsIRDFService*
|
||||
RDFService()
|
||||
{
|
||||
return gRDF;
|
||||
}
|
||||
|
||||
static nsICollation*
|
||||
GetCollation();
|
||||
|
||||
#define XUL_RESOURCE(ident, uri) static nsIRDFResource* ident
|
||||
#define XUL_LITERAL(ident, val) static nsIRDFLiteral* ident
|
||||
#include "nsXULResourceList.h"
|
||||
#undef XUL_RESOURCE
|
||||
#undef XUL_LITERAL
|
||||
};
|
||||
|
||||
#endif // nsXULContentUtils_h__
|
@ -1,13 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// N.B., no include guard! We'll include this multiple times in some
|
||||
// files.
|
||||
|
||||
XUL_RESOURCE(NC_child, NC_NAMESPACE_URI "child");
|
||||
XUL_RESOURCE(NC_Folder, NC_NAMESPACE_URI "Folder");
|
||||
XUL_RESOURCE(NC_open, NC_NAMESPACE_URI "open");
|
||||
|
||||
XUL_LITERAL(true_, u"true");
|
File diff suppressed because it is too large
Load Diff
@ -1,561 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateBuilder_h__
|
||||
#define nsXULTemplateBuilder_h__
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "nsStubDocumentObserver.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
class nsIObserverService;
|
||||
class nsIRDFCompositeDataSource;
|
||||
class nsIRDFContainerUtils;
|
||||
class nsIRDFDataSource;
|
||||
class nsIRDFService;
|
||||
class nsIScriptSecurityManager;
|
||||
class nsIXULTemplateQueryProcessor;
|
||||
class nsTemplateCondition;
|
||||
class nsTemplateRule;
|
||||
class nsTemplateMatch;
|
||||
class nsTemplateQuerySet;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class XULBuilderListener;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
/**
|
||||
* An object that translates an RDF graph into a presentation using a
|
||||
* set of rules.
|
||||
*/
|
||||
class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
|
||||
public nsIObserver,
|
||||
public nsStubDocumentObserver,
|
||||
public nsWrapperCache
|
||||
{
|
||||
void CleanUp(bool aIsFinal);
|
||||
void DestroyMatchMap();
|
||||
|
||||
public:
|
||||
nsresult Init();
|
||||
|
||||
nsresult InitGlobals();
|
||||
|
||||
/**
|
||||
* Clear the template builder structures. The aIsFinal flag is set to true
|
||||
* when the template is going away.
|
||||
*/
|
||||
virtual void Uninit(bool aIsFinal);
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
|
||||
nsIXULTemplateBuilder)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
Element* GetParentObject()
|
||||
{
|
||||
return mRoot;
|
||||
}
|
||||
|
||||
Element* GetRoot()
|
||||
{
|
||||
return mRoot;
|
||||
}
|
||||
nsISupports* GetDatasource();
|
||||
void SetDatasource(nsISupports* aDatasource, mozilla::ErrorResult& aError);
|
||||
nsIRDFCompositeDataSource* GetDatabase()
|
||||
{
|
||||
return mCompDB;
|
||||
}
|
||||
nsIXULTemplateResult* GetRootResult()
|
||||
{
|
||||
return mRootResult;
|
||||
}
|
||||
void Rebuild(mozilla::ErrorResult& aError);
|
||||
void Refresh(mozilla::ErrorResult& aError);
|
||||
void AddResult(nsIXULTemplateResult* aResult, nsINode& aQueryNode,
|
||||
mozilla::ErrorResult& aError);
|
||||
void RemoveResult(nsIXULTemplateResult* aResult,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ReplaceResult(nsIXULTemplateResult* aOldResult,
|
||||
nsIXULTemplateResult* aNewResult,
|
||||
nsINode& aQueryNode,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ResultBindingChanged(nsIXULTemplateResult* aResult,
|
||||
mozilla::ErrorResult& aError);
|
||||
nsIXULTemplateResult* GetResultForId(const nsAString& aId,
|
||||
mozilla::ErrorResult& aError);
|
||||
virtual nsIXULTemplateResult* GetResultForContent(Element& aElement)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
virtual bool HasGeneratedContent(nsIRDFResource* aResource,
|
||||
const nsAString& aTag,
|
||||
mozilla::ErrorResult& aError)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void AddRuleFilter(nsINode& aRule, nsIXULTemplateRuleFilter* aFilter,
|
||||
mozilla::ErrorResult& aError);
|
||||
void AddListener(mozilla::dom::XULBuilderListener& aListener);
|
||||
void RemoveListener(mozilla::dom::XULBuilderListener& aListener);
|
||||
|
||||
// nsIXULTemplateBuilder interface
|
||||
NS_DECL_NSIXULTEMPLATEBUILDER
|
||||
|
||||
// nsIObserver Interface
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
/**
|
||||
* Remove an old result and/or add a new result. This method will retrieve
|
||||
* the set of containers where the result could be inserted and either add
|
||||
* the new result to those containers, or remove the result from those
|
||||
* containers. UpdateResultInContainer is called for each container.
|
||||
*
|
||||
* @param aOldResult result to remove
|
||||
* @param aNewResult result to add
|
||||
* @param aQueryNode query node for new result
|
||||
*/
|
||||
nsresult
|
||||
UpdateResult(nsIXULTemplateResult* aOldResult,
|
||||
nsIXULTemplateResult* aNewResult,
|
||||
nsINode* aQueryNode);
|
||||
|
||||
/**
|
||||
* Remove an old result and/or add a new result from a specific container.
|
||||
*
|
||||
* @param aOldResult result to remove
|
||||
* @param aNewResult result to add
|
||||
* @param aQueryNode queryset for the new result
|
||||
* @param aOldId id of old result
|
||||
* @param aNewId id of new result
|
||||
* @param aInsertionPoint container to remove or add result inside
|
||||
*/
|
||||
nsresult
|
||||
UpdateResultInContainer(nsIXULTemplateResult* aOldResult,
|
||||
nsIXULTemplateResult* aNewResult,
|
||||
nsTemplateQuerySet* aQuerySet,
|
||||
nsIRDFResource* aOldId,
|
||||
nsIRDFResource* aNewId,
|
||||
Element* aInsertionPoint);
|
||||
|
||||
nsresult
|
||||
ComputeContainmentProperties();
|
||||
|
||||
static bool
|
||||
IsTemplateElement(nsIContent* aContent);
|
||||
|
||||
virtual nsresult
|
||||
RebuildAll() = 0; // must be implemented by subclasses
|
||||
|
||||
void RunnableRebuild() { Rebuild(); }
|
||||
void RunnableLoadAndRebuild() {
|
||||
Uninit(false); // Reset results
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = mRoot ? mRoot->GetComposedDoc() : nullptr;
|
||||
if (doc) {
|
||||
bool shouldDelay;
|
||||
LoadDataSources(doc, &shouldDelay);
|
||||
if (!shouldDelay) {
|
||||
Rebuild();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mRoot should not be cleared until after Uninit is finished so that
|
||||
// generated content can be removed during uninitialization.
|
||||
void UninitFalse() { Uninit(false); mRoot = nullptr; }
|
||||
void UninitTrue() { Uninit(true); mRoot = nullptr; }
|
||||
|
||||
/**
|
||||
* Find the <template> tag that applies for this builder
|
||||
*/
|
||||
nsresult
|
||||
GetTemplateRoot(Element** aResult);
|
||||
|
||||
/**
|
||||
* Compile the template's queries
|
||||
*/
|
||||
nsresult
|
||||
CompileQueries();
|
||||
|
||||
/**
|
||||
* Compile the template given a <template> in aTemplate. This function
|
||||
* is called recursively to handle queries inside a queryset. For the
|
||||
* outer pass, aIsQuerySet will be false, while the inner pass this will
|
||||
* be true.
|
||||
*
|
||||
* aCanUseTemplate will be set to true if the template's queries could be
|
||||
* compiled, and false otherwise. If false, the entire template is
|
||||
* invalid.
|
||||
*
|
||||
* @param aTemplate <template> to compile
|
||||
* @param aQuerySet first queryset
|
||||
* @param aIsQuerySet true if
|
||||
* @param aPriority the queryset index, incremented when a new one is added
|
||||
* @param aCanUseTemplate true if template is valid
|
||||
*/
|
||||
nsresult
|
||||
CompileTemplate(Element* aTemplate,
|
||||
nsTemplateQuerySet* aQuerySet,
|
||||
bool aIsQuerySet,
|
||||
int32_t* aPriority,
|
||||
bool* aCanUseTemplate);
|
||||
|
||||
/**
|
||||
* Compile a query using the extended syntax. For backwards compatible RDF
|
||||
* syntax where there is no <query>, the <conditions> becomes the query.
|
||||
*
|
||||
* @param aRuleElement <rule> element
|
||||
* @param aActionElement <action> element
|
||||
* @param aMemberVariable member variable for the query
|
||||
* @param aQuerySet the queryset
|
||||
*/
|
||||
nsresult
|
||||
CompileExtendedQuery(Element* aRuleElement,
|
||||
nsIContent* aActionElement,
|
||||
nsAtom* aMemberVariable,
|
||||
nsTemplateQuerySet* aQuerySet);
|
||||
|
||||
/**
|
||||
* Determine the ref variable and tag from inside a RDF query.
|
||||
*/
|
||||
void DetermineRDFQueryRef(nsIContent* aQueryElement, nsAtom** tag);
|
||||
|
||||
/**
|
||||
* Determine the member variable from inside an action body. It will be
|
||||
* the value of the uri attribute on a node.
|
||||
*/
|
||||
already_AddRefed<nsAtom> DetermineMemberVariable(nsIContent* aElement);
|
||||
|
||||
/**
|
||||
* Compile a simple query. A simple query is one that doesn't have a
|
||||
* <query> and should use a default query which would normally just return
|
||||
* a list of children of the reference point.
|
||||
*
|
||||
* @param aRuleElement the <rule>
|
||||
* @param aQuerySet the query set
|
||||
* @param aCanUseTemplate true if the query is valid
|
||||
*/
|
||||
nsresult
|
||||
CompileSimpleQuery(Element* aRuleElement,
|
||||
nsTemplateQuerySet* aQuerySet,
|
||||
bool* aCanUseTemplate);
|
||||
|
||||
/**
|
||||
* Compile the <conditions> tag in a rule
|
||||
*
|
||||
* @param aRule template rule
|
||||
* @param aConditions <conditions> element
|
||||
*/
|
||||
nsresult
|
||||
CompileConditions(nsTemplateRule* aRule, Element* aConditions);
|
||||
|
||||
/**
|
||||
* Compile a <where> tag in a condition. The caller should set
|
||||
* *aCurrentCondition to null for the first condition. This value will be
|
||||
* updated to point to the new condition before returning. The conditions
|
||||
* will be added to the rule aRule by this method.
|
||||
*
|
||||
* @param aRule template rule
|
||||
* @param aCondition <where> element
|
||||
* @param aCurrentCondition compiled condition
|
||||
*/
|
||||
nsresult
|
||||
CompileWhereCondition(nsTemplateRule* aRule,
|
||||
Element* aCondition,
|
||||
nsTemplateCondition** aCurrentCondition);
|
||||
|
||||
/**
|
||||
* Compile the <bindings> for an extended template syntax rule.
|
||||
*/
|
||||
nsresult
|
||||
CompileBindings(nsTemplateRule* aRule, nsIContent* aBindings);
|
||||
|
||||
/**
|
||||
* Compile a single binding for an extended template syntax rule.
|
||||
*/
|
||||
nsresult
|
||||
CompileBinding(nsTemplateRule* aRule, Element* aBinding);
|
||||
|
||||
/**
|
||||
* Add automatic bindings for simple rules
|
||||
*/
|
||||
nsresult
|
||||
AddSimpleRuleBindings(nsTemplateRule* aRule, Element* aElement);
|
||||
|
||||
static void
|
||||
AddBindingsFor(nsXULTemplateBuilder* aSelf,
|
||||
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, bool* 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,
|
||||
bool aIsRDFQuery,
|
||||
bool* aShouldDelayBuilding);
|
||||
|
||||
nsresult
|
||||
InitHTMLTemplateRoot();
|
||||
|
||||
/**
|
||||
* Determine which rule matches a given result. aContainer is used for
|
||||
* tag matching and is optional for non-content generating builders.
|
||||
* The returned matched rule is always one of the rules owned by the
|
||||
* query set aQuerySet.
|
||||
*
|
||||
* @param aContainer parent where generated content will be inserted
|
||||
* @param aResult result to match
|
||||
* @param aQuerySet query set to examine the rules of
|
||||
* @param aMatchedRule [out] rule that has matched, or null if any.
|
||||
* @param aRuleIndex [out] index of the rule
|
||||
*/
|
||||
nsresult
|
||||
DetermineMatchedRule(nsIContent* aContainer,
|
||||
nsIXULTemplateResult* aResult,
|
||||
nsTemplateQuerySet* aQuerySet,
|
||||
nsTemplateRule** aMatchedRule,
|
||||
int16_t *aRuleIndex);
|
||||
|
||||
// XXX sigh, the string template foo doesn't mix with
|
||||
// operator->*() on egcs-1.1.2, so we'll need to explicitly pass
|
||||
// "this" and use good ol' fashioned static callbacks.
|
||||
void
|
||||
ParseAttribute(const nsAString& aAttributeValue,
|
||||
void (*aVariableCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
|
||||
void (*aTextCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
|
||||
void* aClosure);
|
||||
|
||||
nsresult
|
||||
SubstituteText(nsIXULTemplateResult* aMatch,
|
||||
const nsAString& aAttributeValue,
|
||||
nsAString& aResult);
|
||||
|
||||
static void
|
||||
SubstituteTextAppendText(nsXULTemplateBuilder* aThis, const nsAString& aText, void* aClosure);
|
||||
|
||||
static void
|
||||
SubstituteTextReplaceVariable(nsXULTemplateBuilder* aThis, const nsAString& aVariable, void* aClosure);
|
||||
|
||||
/**
|
||||
* Convenience method which gets a resource for a result. If a result
|
||||
* doesn't have a resource set, it will create one from the result's id.
|
||||
*/
|
||||
nsresult GetResultResource(nsIXULTemplateResult* aResult,
|
||||
nsIRDFResource** aResource);
|
||||
|
||||
protected:
|
||||
explicit nsXULTemplateBuilder(Element* aElement);
|
||||
virtual ~nsXULTemplateBuilder();
|
||||
|
||||
nsCOMPtr<nsISupports> mDataSource;
|
||||
nsCOMPtr<nsIRDFDataSource> mDB;
|
||||
nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
|
||||
|
||||
/**
|
||||
* Circular reference, broken when the document is destroyed.
|
||||
*/
|
||||
nsCOMPtr<Element> mRoot;
|
||||
|
||||
/**
|
||||
* The root result, translated from the root element's ref
|
||||
*/
|
||||
nsCOMPtr<nsIXULTemplateResult> mRootResult;
|
||||
|
||||
nsTArray<nsCOMPtr<nsIXULBuilderListener>> mListeners;
|
||||
|
||||
/**
|
||||
* The query processor which generates results
|
||||
*/
|
||||
nsCOMPtr<nsIXULTemplateQueryProcessor> mQueryProcessor;
|
||||
|
||||
/**
|
||||
* The list of querysets
|
||||
*/
|
||||
nsTArray<nsTemplateQuerySet *> mQuerySets;
|
||||
|
||||
/**
|
||||
* Set to true if the rules have already been compiled
|
||||
*/
|
||||
bool mQueriesCompiled;
|
||||
|
||||
/**
|
||||
* The default reference and member variables.
|
||||
*/
|
||||
RefPtr<nsAtom> mRefVariable;
|
||||
RefPtr<nsAtom> mMemberVariable;
|
||||
|
||||
/**
|
||||
* The match map contains nsTemplateMatch objects, one for each unique
|
||||
* match found, keyed by the resource for that match. A particular match
|
||||
* will contain a linked list of all of the matches for that unique result
|
||||
* id. Only one is active at a time. When a match is retracted, look in
|
||||
* the match map, remove it, and apply the next valid match in sequence to
|
||||
* make active.
|
||||
*/
|
||||
nsDataHashtable<nsISupportsHashKey, nsTemplateMatch*> mMatchMap;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsIScriptSecurityManager* gScriptSecurityManager;
|
||||
static nsIPrincipal* gSystemPrincipal;
|
||||
static nsIObserverService* gObserverService;
|
||||
|
||||
enum {
|
||||
eDontTestEmpty = (1 << 0),
|
||||
eDontRecurse = (1 << 1),
|
||||
eLoggingEnabled = (1 << 2)
|
||||
};
|
||||
|
||||
int32_t mFlags;
|
||||
|
||||
/**
|
||||
* Stack-based helper class to maintain a list of ``activated''
|
||||
* resources; i.e., resources for which we are currently building
|
||||
* content.
|
||||
*/
|
||||
class ActivationEntry {
|
||||
public:
|
||||
nsIRDFResource *mResource;
|
||||
ActivationEntry *mPrevious;
|
||||
ActivationEntry **mLink;
|
||||
|
||||
ActivationEntry(nsIRDFResource *aResource, ActivationEntry **aLink)
|
||||
: mResource(aResource),
|
||||
mPrevious(*aLink),
|
||||
mLink(aLink) { *mLink = this; }
|
||||
|
||||
~ActivationEntry() { *mLink = mPrevious; }
|
||||
};
|
||||
|
||||
/**
|
||||
* The top of the stack of resources that we're currently building
|
||||
* content for.
|
||||
*/
|
||||
ActivationEntry *mTop;
|
||||
|
||||
/**
|
||||
* Determine if a resource is currently on the activation stack.
|
||||
*/
|
||||
bool
|
||||
IsActivated(nsIRDFResource *aResource);
|
||||
|
||||
/**
|
||||
* Returns true if content may be generated for a result, or false if it
|
||||
* cannot, for example, if it would be created inside a closed container.
|
||||
* Those results will be generated when the container is opened.
|
||||
* If false is returned, no content should be generated. Possible
|
||||
* insertion locations may optionally be set for new content, depending on
|
||||
* the builder being used. Note that *aLocations or some items within
|
||||
* aLocations may be null.
|
||||
*/
|
||||
virtual bool
|
||||
GetInsertionLocations(nsIXULTemplateResult* aResult,
|
||||
nsCOMArray<Element>** aLocations) = 0;
|
||||
|
||||
/**
|
||||
* Must be implemented by subclasses. Handle removing the generated
|
||||
* output for aOldMatch and adding new output for aNewMatch. Either
|
||||
* aOldMatch or aNewMatch may be null. aContext is the location returned
|
||||
* from the call to MayGenerateResult.
|
||||
*/
|
||||
virtual nsresult
|
||||
ReplaceMatch(nsIXULTemplateResult* aOldResult,
|
||||
nsTemplateMatch* aNewMatch,
|
||||
nsTemplateRule* aNewMatchRule,
|
||||
Element* aContext) = 0;
|
||||
|
||||
/**
|
||||
* Must be implemented by subclasses. Handle change in bound
|
||||
* variable values for aResult. aModifiedVars contains the set
|
||||
* of variables that have changed.
|
||||
* @param aResult the ersult for which variable bindings has changed.
|
||||
* @param aModifiedVars the set of variables for which the bindings
|
||||
* have changed.
|
||||
*/
|
||||
virtual nsresult
|
||||
SynchronizeResult(nsIXULTemplateResult* aResult) = 0;
|
||||
|
||||
/**
|
||||
* Output a new match or removed match to the console.
|
||||
*
|
||||
* @param aId id of the result
|
||||
* @param aMatch new or removed match
|
||||
* @param aIsNew true for new matched, false for removed matches
|
||||
*/
|
||||
void
|
||||
OutputMatchToLog(nsIRDFResource* aId,
|
||||
nsTemplateMatch* aMatch,
|
||||
bool aIsNew);
|
||||
|
||||
virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Start observing events from the observer service and the given
|
||||
* document.
|
||||
*
|
||||
* @param aDocument the document to observe
|
||||
*/
|
||||
void StartObserving(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Stop observing events from the observer service and any associated
|
||||
* document.
|
||||
*/
|
||||
void StopObserving();
|
||||
|
||||
/**
|
||||
* Document that we're observing. Weak ref!
|
||||
*/
|
||||
nsIDocument* mObservedDocument;
|
||||
};
|
||||
|
||||
nsresult NS_NewXULContentBuilder(Element* aElement,
|
||||
nsIXULTemplateBuilder** aBuilder);
|
||||
|
||||
#endif // nsXULTemplateBuilder_h__
|
File diff suppressed because it is too large
Load Diff
@ -1,355 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
#ifndef nsXULTemplateQueryProcessorRDF_h__
|
||||
#define nsXULTemplateQueryProcessorRDF_h__
|
||||
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFContainerUtils.h"
|
||||
#include "nsIRDFDataSource.h"
|
||||
#include "nsIRDFObserver.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
#include "nsCollationCID.h"
|
||||
|
||||
#include "nsResourceSet.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsRDFQuery.h"
|
||||
#include "nsRDFBinding.h"
|
||||
#include "nsXULTemplateResultSetRDF.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsString.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
extern mozilla::LazyLogModule gXULTemplateLog;
|
||||
|
||||
class nsIContent;
|
||||
class nsXULTemplateResultRDF;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An object that generates results from a query on an RDF graph
|
||||
*/
|
||||
class nsXULTemplateQueryProcessorRDF final : public nsIXULTemplateQueryProcessor,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
public:
|
||||
typedef nsTArray<RefPtr<nsXULTemplateResultRDF> > ResultArray;
|
||||
|
||||
nsXULTemplateQueryProcessorRDF();
|
||||
|
||||
nsresult InitGlobals();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateQueryProcessorRDF,
|
||||
nsIXULTemplateQueryProcessor)
|
||||
|
||||
// nsIXULTemplateQueryProcessor interface
|
||||
NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR
|
||||
|
||||
// nsIRDFObserver interface
|
||||
NS_DECL_NSIRDFOBSERVER
|
||||
|
||||
/*
|
||||
* Propagate all changes through the rule network when an assertion is
|
||||
* added to the graph, adding any new results.
|
||||
*/
|
||||
nsresult
|
||||
Propagate(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
/*
|
||||
* Retract all changes through the rule network when an assertion is
|
||||
* removed from the graph, removing any results that no longer match.
|
||||
*/
|
||||
nsresult
|
||||
Retract(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
/*
|
||||
* Synchronize results when the graph changes, updating their bindings.
|
||||
*/
|
||||
nsresult
|
||||
SynchronizeAll(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget);
|
||||
|
||||
/*
|
||||
* Return true if a resource is a container
|
||||
*/
|
||||
nsresult
|
||||
CheckContainer(nsIRDFResource* aTargetResource,
|
||||
bool* aIsContainer);
|
||||
|
||||
/*
|
||||
* Check if a resource does not have any children
|
||||
*/
|
||||
nsresult
|
||||
CheckEmpty(nsIRDFResource* aTargetResource,
|
||||
bool* aIsEmpty);
|
||||
|
||||
/**
|
||||
* Check if a resource is a separator
|
||||
*/
|
||||
nsresult
|
||||
CheckIsSeparator(nsIRDFResource* aResource, bool* aIsSeparator);
|
||||
|
||||
/*
|
||||
* Compute the containment properties which are additional arcs which
|
||||
* indicate that a node is a container, in additional to the RDF container
|
||||
* tests. The computed list is stored in mContainmentProperties
|
||||
*/
|
||||
nsresult
|
||||
ComputeContainmentProperties(nsIDOMNode* aRootNode);
|
||||
|
||||
/**
|
||||
* Compile a query that uses the extended template syntax. The last
|
||||
* compiled node of the query is returned as aLastNode. This node will
|
||||
* have been added to mAllTests which owns the node.
|
||||
*/
|
||||
nsresult
|
||||
CompileExtendedQuery(nsRDFQuery* aQuery,
|
||||
nsIContent* aConditions,
|
||||
TestNode** aLastNode);
|
||||
|
||||
/**
|
||||
* Compile a single query child and return the compiled node in aResult.
|
||||
* This node will have been added to mAllTests which owns the node and
|
||||
* set as a child of aParentNode.
|
||||
*/
|
||||
virtual nsresult
|
||||
CompileQueryChild(nsAtom* aTag,
|
||||
nsRDFQuery* aQuery,
|
||||
nsIContent* aConditions,
|
||||
TestNode* aParentNode,
|
||||
TestNode** aResult);
|
||||
|
||||
/**
|
||||
* Parse the value of a property test assertion for a condition or a simple
|
||||
* rule based on the parseType attribute into the appropriate literal type.
|
||||
*/
|
||||
nsresult ParseLiteral(const nsString& aParseType,
|
||||
const nsString& aValue,
|
||||
nsIRDFNode** aResult);
|
||||
|
||||
/**
|
||||
* Compile a <triple> condition and return the compiled node in aResult.
|
||||
* This node will have been added to mAllTests which owns the node and
|
||||
* set as a child of aParentNode.
|
||||
*/
|
||||
nsresult
|
||||
CompileTripleCondition(nsRDFQuery* aQuery,
|
||||
Element* aCondition,
|
||||
TestNode* aParentNode,
|
||||
TestNode** aResult);
|
||||
|
||||
/**
|
||||
* Compile a <member> condition and return the compiled node in aResult.
|
||||
* This node will have been added to mAllTests which owns the node and
|
||||
* set as a child of aParentNode.
|
||||
*/
|
||||
nsresult
|
||||
CompileMemberCondition(nsRDFQuery* aQuery,
|
||||
Element* aCondition,
|
||||
TestNode* aParentNode,
|
||||
TestNode** aResult);
|
||||
|
||||
/**
|
||||
* Add the default rules shared by all simple queries. This creates
|
||||
* the content start node followed by a member test. The member TestNode
|
||||
* is returned in aChildNode. Both nodes will have been added to mAllTests
|
||||
* which owns the nodes.
|
||||
*/
|
||||
nsresult
|
||||
AddDefaultSimpleRules(nsRDFQuery* aQuery,
|
||||
TestNode** aChildNode);
|
||||
|
||||
/**
|
||||
* Compile a query that's specified using the simple template
|
||||
* syntax. Each TestNode is created in a chain, the last compiled node
|
||||
* is returned as aLastNode. All nodes will have been added to mAllTests
|
||||
* which owns the nodes.
|
||||
*/
|
||||
nsresult
|
||||
CompileSimpleQuery(nsRDFQuery* aQuery,
|
||||
mozilla::dom::Element* aQueryElement,
|
||||
TestNode** aLastNode);
|
||||
|
||||
RDFBindingSet*
|
||||
GetBindingsForRule(nsIDOMNode* aRule);
|
||||
|
||||
/*
|
||||
* Indicate that a result is dependant on a particular resource. When an
|
||||
* assertion is added to or removed from the graph involving that
|
||||
* resource, that result must be recalculated.
|
||||
*/
|
||||
void
|
||||
AddBindingDependency(nsXULTemplateResultRDF* aResult,
|
||||
nsIRDFResource* aResource);
|
||||
|
||||
/**
|
||||
* Remove a dependency a result has on a particular resource.
|
||||
*/
|
||||
void
|
||||
RemoveBindingDependency(nsXULTemplateResultRDF* aResult,
|
||||
nsIRDFResource* aResource);
|
||||
|
||||
/**
|
||||
* A memory element is a hash of an RDF triple. One exists for each triple
|
||||
* that was involved in generating a result. This function adds this to a
|
||||
* map, keyed by memory element, when the value is a list of results that
|
||||
* depend on that memory element. When an RDF triple is removed from the
|
||||
* datasource, RetractElement is called, and this map is examined to
|
||||
* determine which results are no longer valid.
|
||||
*/
|
||||
nsresult
|
||||
AddMemoryElements(const Instantiation& aInst,
|
||||
nsXULTemplateResultRDF* aResult);
|
||||
|
||||
/**
|
||||
* Remove the memory elements associated with a result when the result is
|
||||
* no longer being used.
|
||||
*/
|
||||
nsresult
|
||||
RemoveMemoryElements(const Instantiation& aInst,
|
||||
nsXULTemplateResultRDF* aResult);
|
||||
|
||||
/**
|
||||
* Remove the results associated with a memory element since the
|
||||
* RDF triple the memory element is a hash of has been removed.
|
||||
*/
|
||||
void RetractElement(const MemoryElement& aMemoryElement);
|
||||
|
||||
/**
|
||||
* Return the index of a result's resource in its RDF container
|
||||
*/
|
||||
int32_t
|
||||
GetContainerIndexOf(nsIXULTemplateResult* aResult);
|
||||
|
||||
/**
|
||||
* Given a result and a predicate to sort on, get the target value of
|
||||
* the triple to use for sorting. The sort predicate is the predicate
|
||||
* with '?sort=true' appended.
|
||||
*/
|
||||
nsresult
|
||||
GetSortValue(nsIXULTemplateResult* aResult,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsIRDFResource* aSortPredicate,
|
||||
nsISupports** aResultNode);
|
||||
|
||||
nsIRDFDataSource* GetDataSource() { return mDB; }
|
||||
|
||||
nsIXULTemplateBuilder* GetBuilder() { return mBuilder; }
|
||||
|
||||
nsResourceSet& ContainmentProperties() { return mContainmentProperties; }
|
||||
|
||||
nsresult
|
||||
Log(const char* aOperation,
|
||||
nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
#define LOG(_op, _src, _prop, _targ) \
|
||||
Log(_op, _src, _prop, _targ)
|
||||
|
||||
protected:
|
||||
~nsXULTemplateQueryProcessorRDF();
|
||||
|
||||
// We are an observer of the composite datasource. The cycle is
|
||||
// broken when the document is destroyed.
|
||||
nsCOMPtr<nsIRDFDataSource> mDB;
|
||||
|
||||
// weak reference to the builder, cleared when the document is destroyed
|
||||
nsIXULTemplateBuilder* mBuilder;
|
||||
|
||||
// true if the query processor has been initialized
|
||||
bool mQueryProcessorRDFInited;
|
||||
|
||||
// true if results have been generated. Once set, bindings can no longer
|
||||
// be added. If they were, the binding value arrays for results that have
|
||||
// already been generated would be the wrong size
|
||||
bool mGenerationStarted;
|
||||
|
||||
// nesting level for RDF batch notifications
|
||||
int32_t mUpdateBatchNest;
|
||||
|
||||
// containment properties that are checked to determine if a resource is
|
||||
// a container
|
||||
nsResourceSet mContainmentProperties;
|
||||
|
||||
// the end node of the default simple node hierarchy
|
||||
TestNode* mSimpleRuleMemberTest;
|
||||
|
||||
// the reference variable
|
||||
RefPtr<nsAtom> mRefVariable;
|
||||
|
||||
// the last ref that was calculated, used for simple rules
|
||||
nsCOMPtr<nsIXULTemplateResult> mLastRef;
|
||||
|
||||
/**
|
||||
* A map between nsIRDFNodes that form the left-hand side (the subject) of
|
||||
* a <binding> and an array of nsIXULTemplateResults. When a new assertion
|
||||
* is added to the graph involving a particular rdf node, it is looked up
|
||||
* in this binding map. If it exists, the corresponding results must then
|
||||
* be synchronized.
|
||||
*/
|
||||
nsClassHashtable<nsISupportsHashKey, ResultArray> mBindingDependencies;
|
||||
|
||||
/**
|
||||
* A map between memory elements and an array of nsIXULTemplateResults.
|
||||
* When a triple is unasserted from the graph, the corresponding results
|
||||
* no longer match so they must be removed.
|
||||
*/
|
||||
nsClassHashtable<nsUint32HashKey,
|
||||
nsCOMArray<nsXULTemplateResultRDF> > mMemoryElementToResultMap;
|
||||
|
||||
// map of the rules to the bindings for those rules.
|
||||
// XXXndeakin this might be better just as an array since there is usually
|
||||
// ten or fewer rules
|
||||
nsRefPtrHashtable<nsISupportsHashKey, RDFBindingSet> mRuleToBindingsMap;
|
||||
|
||||
/**
|
||||
* The queries
|
||||
*/
|
||||
nsTArray<nsCOMPtr<nsITemplateRDFQuery> > mQueries;
|
||||
|
||||
/**
|
||||
* All of the RDF tests in the rule network, which are checked when a new
|
||||
* assertion is added to the graph. This is a subset of mAllTests, which
|
||||
* also includes non-RDF tests.
|
||||
*/
|
||||
ReteNodeSet mRDFTests;
|
||||
|
||||
/**
|
||||
* All of the tests in the rule network, owned by this list
|
||||
*/
|
||||
ReteNodeSet mAllTests;
|
||||
|
||||
// pseudo-constants
|
||||
static nsrefcnt gRefCnt;
|
||||
|
||||
public:
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsIRDFResource* kNC_BookmarkSeparator;
|
||||
static nsIRDFResource* kRDF_type;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateQueryProcessorRDF_h__
|
@ -1,507 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "prprf.h"
|
||||
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
|
||||
#include "nsIURI.h"
|
||||
#include "nsIFileChannel.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "nsXULTemplateBuilder.h"
|
||||
#include "nsXULTemplateResultStorage.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "nsXULSortService.h"
|
||||
|
||||
#include "mozIStorageService.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsTemplateMatch.h"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateResultSetStorage
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateResultSetStorage, nsISimpleEnumerator)
|
||||
|
||||
|
||||
nsXULTemplateResultSetStorage::nsXULTemplateResultSetStorage(mozIStorageStatement* aStatement)
|
||||
: mStatement(aStatement)
|
||||
{
|
||||
uint32_t count;
|
||||
nsresult rv = aStatement->GetColumnCount(&count);
|
||||
if (NS_FAILED(rv)) {
|
||||
mStatement = nullptr;
|
||||
return;
|
||||
}
|
||||
for (uint32_t c = 0; c < count; c++) {
|
||||
nsAutoCString name;
|
||||
rv = aStatement->GetColumnName(c, name);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
RefPtr<nsAtom> columnName = NS_Atomize(NS_LITERAL_CSTRING("?") + name);
|
||||
mColumnNames.AppendElement(columnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetStorage::HasMoreElements(bool *aResult)
|
||||
{
|
||||
if (!mStatement) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv = mStatement->ExecuteStep(aResult);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Because the nsXULTemplateResultSetStorage is owned by many nsXULTemplateResultStorage objects,
|
||||
// it could live longer than it needed to get results.
|
||||
// So we destroy the statement to free resources when all results are fetched
|
||||
if (!*aResult) {
|
||||
mStatement = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetStorage::GetNext(nsISupports **aResult)
|
||||
{
|
||||
nsXULTemplateResultStorage* result =
|
||||
new nsXULTemplateResultStorage(this);
|
||||
*aResult = result;
|
||||
NS_ADDREF(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
nsXULTemplateResultSetStorage::GetColumnIndex(nsAtom* aColumnName)
|
||||
{
|
||||
int32_t count = mColumnNames.Length();
|
||||
for (int32_t c = 0; c < count; c++) {
|
||||
if (mColumnNames[c] == aColumnName)
|
||||
return c;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
nsXULTemplateResultSetStorage::FillColumnValues(nsCOMArray<nsIVariant>& aArray)
|
||||
{
|
||||
if (!mStatement)
|
||||
return;
|
||||
|
||||
int32_t count = mColumnNames.Length();
|
||||
|
||||
for (int32_t c = 0; c < count; c++) {
|
||||
RefPtr<nsVariant> value = new nsVariant();
|
||||
|
||||
int32_t type;
|
||||
mStatement->GetTypeOfIndex(c, &type);
|
||||
|
||||
if (type == mStatement->VALUE_TYPE_INTEGER) {
|
||||
int64_t val = mStatement->AsInt64(c);
|
||||
value->SetAsInt64(val);
|
||||
}
|
||||
else if (type == mStatement->VALUE_TYPE_FLOAT) {
|
||||
double val = mStatement->AsDouble(c);
|
||||
value->SetAsDouble(val);
|
||||
}
|
||||
else {
|
||||
nsAutoString val;
|
||||
nsresult rv = mStatement->GetString(c, val);
|
||||
if (NS_FAILED(rv))
|
||||
value->SetAsAString(EmptyString());
|
||||
else
|
||||
value->SetAsAString(val);
|
||||
}
|
||||
aArray.AppendObject(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateQueryProcessorStorage
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateQueryProcessorStorage,
|
||||
nsIXULTemplateQueryProcessor)
|
||||
|
||||
|
||||
nsXULTemplateQueryProcessorStorage::nsXULTemplateQueryProcessorStorage()
|
||||
: mGenerationStarted(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::GetDatasource(nsIArray* aDataSources,
|
||||
nsIDOMNode* aRootNode,
|
||||
bool aIsTrusted,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
bool* aShouldDelayBuilding,
|
||||
nsISupports** aReturn)
|
||||
{
|
||||
*aReturn = nullptr;
|
||||
*aShouldDelayBuilding = false;
|
||||
|
||||
if (!aIsTrusted) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
uint32_t length;
|
||||
nsresult rv = aDataSources->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (length == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We get only the first uri. This query processor supports
|
||||
// only one database at a time.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
uri = do_QueryElementAt(aDataSources, 0);
|
||||
|
||||
if (!uri) {
|
||||
// No uri in the list of datasources
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<mozIStorageService> storage =
|
||||
do_GetService("@mozilla.org/storage/service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> databaseFile;
|
||||
nsAutoCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (scheme.EqualsLiteral("profile")) {
|
||||
|
||||
nsAutoCString path;
|
||||
rv = uri->GetPathQueryRef(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (path.IsEmpty()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
|
||||
getter_AddRefs(databaseFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = databaseFile->AppendNative(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
nsCOMPtr<nsINode> node = do_QueryInterface(aRootNode);
|
||||
|
||||
// The following channel is never openend, so it does not matter what
|
||||
// securityFlags we pass; let's follow the principle of least privilege.
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
uri,
|
||||
node,
|
||||
nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED,
|
||||
nsIContentPolicy::TYPE_OTHER);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFileChannel> fileChannel = do_QueryInterface(channel, &rv);
|
||||
if (NS_FAILED(rv)) { // if it fails, not a file url
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_BAD_URI);
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = fileChannel->GetFile(getter_AddRefs(databaseFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// ok now we have an URI of a sqlite file
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
rv = storage->OpenDatabase(databaseFile, getter_AddRefs(connection));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_CANNOT_OPEN_DATABASE);
|
||||
return rv;
|
||||
}
|
||||
|
||||
connection.forget(aReturn);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::InitializeForBuilding(nsISupports* aDatasource,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aRootNode)
|
||||
{
|
||||
NS_ENSURE_STATE(!mGenerationStarted);
|
||||
|
||||
mStorageConnection = do_QueryInterface(aDatasource);
|
||||
if (!mStorageConnection)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
bool ready;
|
||||
mStorageConnection->GetConnectionReady(&ready);
|
||||
if (!ready)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::Done()
|
||||
{
|
||||
mGenerationStarted = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::CompileQuery(nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aQueryNode,
|
||||
nsAtom* aRefVariable,
|
||||
nsAtom* aMemberVariable,
|
||||
nsISupports** aReturn)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> childNodes;
|
||||
aQueryNode->GetChildNodes(getter_AddRefs(childNodes));
|
||||
|
||||
uint32_t length;
|
||||
childNodes->GetLength(&length);
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement;
|
||||
nsCOMPtr<nsIContent> queryContent = do_QueryInterface(aQueryNode);
|
||||
nsAutoString sqlQuery;
|
||||
|
||||
// Let's get all text nodes (which should be the query)
|
||||
if (!nsContentUtils::GetNodeTextContent(queryContent, false, sqlQuery, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsresult rv = mStorageConnection->CreateStatement(NS_ConvertUTF16toUTF8(sqlQuery),
|
||||
getter_AddRefs(statement));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_BAD_QUERY);
|
||||
return rv;
|
||||
}
|
||||
|
||||
uint32_t parameterCount = 0;
|
||||
for (nsIContent* child = queryContent->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
|
||||
if (child->NodeInfo()->Equals(nsGkAtoms::param, kNameSpaceID_XUL)) {
|
||||
nsAutoString value;
|
||||
if (!nsContentUtils::GetNodeTextContent(child, false, value, fallible)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
uint32_t index = parameterCount;
|
||||
nsAutoString name, indexValue;
|
||||
|
||||
if (child->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::name,
|
||||
name)) {
|
||||
rv = statement->GetParameterIndex(NS_ConvertUTF16toUTF8(name),
|
||||
&index);
|
||||
if (NS_FAILED(rv)) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_UNKNOWN_QUERY_PARAMETER);
|
||||
return rv;
|
||||
}
|
||||
parameterCount++;
|
||||
} else if (child->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::index,
|
||||
indexValue)) {
|
||||
PR_sscanf(NS_ConvertUTF16toUTF8(indexValue).get(),"%d",&index);
|
||||
if (index > 0)
|
||||
index--;
|
||||
}
|
||||
else {
|
||||
parameterCount++;
|
||||
}
|
||||
|
||||
static Element::AttrValuesArray sTypeValues[] =
|
||||
{ &nsGkAtoms::int32, &nsGkAtoms::integer, &nsGkAtoms::int64,
|
||||
&nsGkAtoms::null, &nsGkAtoms::double_, &nsGkAtoms::string, nullptr };
|
||||
|
||||
int32_t typeError = 1;
|
||||
int32_t typeValue = child->AsElement()->
|
||||
FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::type, sTypeValues,
|
||||
eCaseMatters);
|
||||
rv = NS_ERROR_ILLEGAL_VALUE;
|
||||
int32_t valInt32 = 0;
|
||||
int64_t valInt64 = 0;
|
||||
double valFloat = 0;
|
||||
|
||||
switch (typeValue) {
|
||||
case 0:
|
||||
case 1:
|
||||
typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%d",&valInt32);
|
||||
if (typeError > 0)
|
||||
rv = statement->BindInt32ByIndex(index, valInt32);
|
||||
break;
|
||||
case 2:
|
||||
typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%lld",&valInt64);
|
||||
if (typeError > 0)
|
||||
rv = statement->BindInt64ByIndex(index, valInt64);
|
||||
break;
|
||||
case 3:
|
||||
rv = statement->BindNullByIndex(index);
|
||||
break;
|
||||
case 4:
|
||||
typeError = PR_sscanf(NS_ConvertUTF16toUTF8(value).get(),"%lf",&valFloat);
|
||||
if (typeError > 0)
|
||||
rv = statement->BindDoubleByIndex(index, valFloat);
|
||||
break;
|
||||
case 5:
|
||||
case Element::ATTR_MISSING:
|
||||
rv = statement->BindStringByIndex(index, value);
|
||||
break;
|
||||
default:
|
||||
typeError = 0;
|
||||
}
|
||||
|
||||
if (typeError <= 0) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_WRONG_TYPE_QUERY_PARAMETER);
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_STORAGE_QUERY_PARAMETER_NOT_BOUND);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aReturn = statement;
|
||||
NS_IF_ADDREF(*aReturn);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::GenerateResults(nsISupports* aDatasource,
|
||||
nsIXULTemplateResult* aRef,
|
||||
nsISupports* aQuery,
|
||||
nsISimpleEnumerator** aResults)
|
||||
{
|
||||
mGenerationStarted = true;
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> statement = do_QueryInterface(aQuery);
|
||||
if (!statement)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsXULTemplateResultSetStorage* results =
|
||||
new nsXULTemplateResultSetStorage(statement);
|
||||
*aResults = results;
|
||||
NS_ADDREF(*aResults);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::AddBinding(nsIDOMNode* aRuleNode,
|
||||
nsAtom* aVar,
|
||||
nsAtom* aRef,
|
||||
const nsAString& aExpr)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::TranslateRef(nsISupports* aDatasource,
|
||||
const nsAString& aRefString,
|
||||
nsIXULTemplateResult** aRef)
|
||||
{
|
||||
nsXULTemplateResultStorage* result =
|
||||
new nsXULTemplateResultStorage(nullptr);
|
||||
*aRef = result;
|
||||
NS_ADDREF(*aRef);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorStorage::CompareResults(nsIXULTemplateResult* aLeft,
|
||||
nsIXULTemplateResult* aRight,
|
||||
nsAtom* aVar,
|
||||
uint32_t aSortHints,
|
||||
int32_t* aResult)
|
||||
{
|
||||
*aResult = 0;
|
||||
if (!aVar)
|
||||
return NS_OK;
|
||||
|
||||
// We're going to see if values are integers or float, to perform
|
||||
// a suitable comparison
|
||||
nsCOMPtr<nsISupports> leftValue, rightValue;
|
||||
if (aLeft)
|
||||
aLeft->GetBindingObjectFor(aVar, getter_AddRefs(leftValue));
|
||||
if (aRight)
|
||||
aRight->GetBindingObjectFor(aVar, getter_AddRefs(rightValue));
|
||||
|
||||
if (leftValue && rightValue) {
|
||||
nsCOMPtr<nsIVariant> vLeftValue = do_QueryInterface(leftValue);
|
||||
nsCOMPtr<nsIVariant> vRightValue = do_QueryInterface(rightValue);
|
||||
|
||||
if (vLeftValue && vRightValue) {
|
||||
nsresult rv1, rv2;
|
||||
uint16_t vtypeL, vtypeR;
|
||||
vLeftValue->GetDataType(&vtypeL);
|
||||
vRightValue->GetDataType(&vtypeR);
|
||||
|
||||
if (vtypeL == vtypeR) {
|
||||
if (vtypeL == nsIDataType::VTYPE_INT64) {
|
||||
int64_t leftValue, rightValue;
|
||||
rv1 = vLeftValue->GetAsInt64(&leftValue);
|
||||
rv2 = vRightValue->GetAsInt64(&rightValue);
|
||||
if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
|
||||
if (leftValue > rightValue)
|
||||
*aResult = 1;
|
||||
else if (leftValue < rightValue)
|
||||
*aResult = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else if (vtypeL == nsIDataType::VTYPE_DOUBLE) {
|
||||
double leftValue, rightValue;
|
||||
rv1 = vLeftValue->GetAsDouble(&leftValue);
|
||||
rv2 = vRightValue->GetAsDouble(&rightValue);
|
||||
if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
|
||||
if (leftValue > rightValue)
|
||||
*aResult = 1;
|
||||
else if (leftValue < rightValue)
|
||||
*aResult = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Values are not integers or floats, so we just compare them as simple strings
|
||||
nsAutoString leftVal;
|
||||
if (aLeft)
|
||||
aLeft->GetBindingFor(aVar, leftVal);
|
||||
|
||||
nsAutoString rightVal;
|
||||
if (aRight)
|
||||
aRight->GetBindingFor(aVar, rightVal);
|
||||
|
||||
*aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
|
||||
return NS_OK;
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateQueryProcessorStorage_h__
|
||||
#define nsXULTemplateQueryProcessorStorage_h__
|
||||
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
#include "mozIStorageValueArray.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorStorage;
|
||||
|
||||
class nsXULTemplateResultSetStorage final : public nsISimpleEnumerator
|
||||
{
|
||||
private:
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> mStatement;
|
||||
|
||||
nsTArray<RefPtr<nsAtom>> mColumnNames;
|
||||
|
||||
~nsXULTemplateResultSetStorage() {}
|
||||
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator interface
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
explicit nsXULTemplateResultSetStorage(mozIStorageStatement* aStatement);
|
||||
|
||||
int32_t GetColumnIndex(nsAtom* aColumnName);
|
||||
|
||||
void FillColumnValues(nsCOMArray<nsIVariant>& aArray);
|
||||
|
||||
};
|
||||
|
||||
class nsXULTemplateQueryProcessorStorage final : public nsIXULTemplateQueryProcessor
|
||||
{
|
||||
public:
|
||||
|
||||
nsXULTemplateQueryProcessorStorage();
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIXULTemplateQueryProcessor interface
|
||||
NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR
|
||||
|
||||
private:
|
||||
|
||||
~nsXULTemplateQueryProcessorStorage() {}
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> mStorageConnection;
|
||||
bool mGenerationStarted;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateQueryProcessorStorage_h__
|
@ -1,451 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIArray.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
#include "mozilla/dom/XPathEvaluator.h"
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
#include "nsXULSortService.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/XMLHttpRequest.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXMLQuery, nsXMLQuery)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateResultSetXML
|
||||
//
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateResultSetXML, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetXML::HasMoreElements(bool *aResult)
|
||||
{
|
||||
// if GetSnapshotLength failed, then the return type was not a set of
|
||||
// nodes, so just return false in this case.
|
||||
ErrorResult rv;
|
||||
uint32_t length = mResults->GetSnapshotLength(rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
rv.SuppressException();
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*aResult = mPosition < length;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetXML::GetNext(nsISupports **aResult)
|
||||
{
|
||||
ErrorResult rv;
|
||||
nsINode* node = mResults->SnapshotItem(mPosition, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
nsXULTemplateResultXML* result =
|
||||
new nsXULTemplateResultXML(mQuery, node->AsContent(), mBindingSet);
|
||||
|
||||
++mPosition;
|
||||
*aResult = result;
|
||||
NS_ADDREF(result);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//
|
||||
// nsXULTemplateQueryProcessorXML
|
||||
//
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
|
||||
tmp->mRuleToBindingsMap.Clear();
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mEvaluator)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXULTemplateQueryProcessorXML)
|
||||
for (auto it = tmp->mRuleToBindingsMap.Iter(); !it.Done(); it.Next()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mRuleToBindingsMap key");
|
||||
cb.NoteXPCOMChild(it.Key());
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRoot)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvaluator)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateBuilder)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateQueryProcessorXML)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateQueryProcessorXML)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateQueryProcessorXML)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXULTemplateQueryProcessor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULTemplateQueryProcessor)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
/*
|
||||
* Only the first datasource in aDataSource is used, which should be either an
|
||||
* nsIURI of an XML document, or a DOM node. If the former, GetDatasource will
|
||||
* load the document asynchronously and return null in aResult. Once the
|
||||
* document has loaded, the builder's datasource will be set to the XML
|
||||
* document. If the datasource is a DOM node, the node will be returned in
|
||||
* aResult.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::GetDatasource(nsIArray* aDataSources,
|
||||
nsIDOMNode* aRootNode,
|
||||
bool aIsTrusted,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
bool* aShouldDelayBuilding,
|
||||
nsISupports** aResult)
|
||||
{
|
||||
*aResult = nullptr;
|
||||
*aShouldDelayBuilding = false;
|
||||
|
||||
nsresult rv;
|
||||
uint32_t length;
|
||||
|
||||
aDataSources->GetLength(&length);
|
||||
if (length == 0)
|
||||
return NS_OK;
|
||||
|
||||
// we get only the first item, because the query processor supports only
|
||||
// one document as a datasource
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node = do_QueryElementAt(aDataSources, 0);
|
||||
if (node) {
|
||||
return CallQueryInterface(node, aResult);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri = do_QueryElementAt(aDataSources, 0);
|
||||
if (!uri)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsAutoCString uriStr;
|
||||
rv = uri->GetSpec(uriStr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIContent> root = do_QueryInterface(aRootNode);
|
||||
if (!root)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = root->GetUncomposedDoc();
|
||||
if (!doc)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsIPrincipal *docPrincipal = doc->NodePrincipal();
|
||||
|
||||
bool hasHadScriptObject = true;
|
||||
nsIScriptGlobalObject* scriptObject =
|
||||
doc->GetScriptHandlingObject(hasHadScriptObject);
|
||||
NS_ENSURE_STATE(scriptObject);
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequest> req =
|
||||
do_CreateInstance(NS_XMLHTTPREQUEST_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = req->Init(docPrincipal, scriptObject, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = req->Open(NS_LITERAL_CSTRING("GET"), uriStr, true,
|
||||
EmptyString(), EmptyString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<EventTarget> target(do_QueryInterface(req));
|
||||
rv = target->AddEventListener(NS_LITERAL_STRING("load"), this, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = target->AddEventListener(NS_LITERAL_STRING("error"), this, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = req->Send(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mTemplateBuilder = aBuilder;
|
||||
mRequest = req;
|
||||
|
||||
*aShouldDelayBuilding = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::InitializeForBuilding(nsISupports* aDatasource,
|
||||
nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aRootNode)
|
||||
{
|
||||
if (mGenerationStarted)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// the datasource is either a document or a DOM element
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDatasource);
|
||||
if (doc)
|
||||
mRoot = doc->GetDocumentElement();
|
||||
else
|
||||
mRoot = do_QueryInterface(aDatasource);
|
||||
NS_ENSURE_STATE(mRoot);
|
||||
|
||||
mEvaluator = new XPathEvaluator();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::Done()
|
||||
{
|
||||
mGenerationStarted = false;
|
||||
|
||||
mRuleToBindingsMap.Clear();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::CompileQuery(nsIXULTemplateBuilder* aBuilder,
|
||||
nsIDOMNode* aQueryNode,
|
||||
nsAtom* aRefVariable,
|
||||
nsAtom* aMemberVariable,
|
||||
nsISupports** _retval)
|
||||
{
|
||||
*_retval = nullptr;
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aQueryNode);
|
||||
|
||||
nsAutoString expr;
|
||||
if (content->IsElement()) {
|
||||
content->AsElement()->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.Assign('*');
|
||||
|
||||
ErrorResult rv;
|
||||
nsAutoPtr<XPathExpression> compiledexpr;
|
||||
compiledexpr = CreateExpression(expr, content, rv);
|
||||
if (rv.Failed()) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_XPATH);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
RefPtr<nsXMLQuery> query =
|
||||
new nsXMLQuery(this, aMemberVariable, Move(compiledexpr));
|
||||
|
||||
for (nsIContent* condition = content->GetFirstChild();
|
||||
condition;
|
||||
condition = condition->GetNextSibling()) {
|
||||
|
||||
if (condition->NodeInfo()->Equals(nsGkAtoms::assign,
|
||||
kNameSpaceID_XUL)) {
|
||||
nsAutoString var;
|
||||
condition->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::var, var);
|
||||
|
||||
nsAutoString expr;
|
||||
condition->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::expr, expr);
|
||||
|
||||
// ignore assignments without a variable or an expression
|
||||
if (!var.IsEmpty() && !expr.IsEmpty()) {
|
||||
compiledexpr = CreateExpression(expr, condition, rv);
|
||||
if (rv.Failed()) {
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_ASSIGN_XPATH);
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
RefPtr<nsAtom> varatom = NS_Atomize(var);
|
||||
|
||||
query->AddBinding(varatom, Move(compiledexpr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query.forget(_retval);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::GenerateResults(nsISupports* aDatasource,
|
||||
nsIXULTemplateResult* aRef,
|
||||
nsISupports* aQuery,
|
||||
nsISimpleEnumerator** aResults)
|
||||
{
|
||||
if (!aQuery)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
mGenerationStarted = true;
|
||||
|
||||
nsCOMPtr<nsXMLQuery> xmlquery = do_QueryInterface(aQuery);
|
||||
if (!xmlquery)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
nsCOMPtr<nsISupports> supports;
|
||||
nsCOMPtr<nsINode> context;
|
||||
if (aRef)
|
||||
aRef->GetBindingObjectFor(xmlquery->GetMemberVariable(),
|
||||
getter_AddRefs(supports));
|
||||
context = do_QueryInterface(supports);
|
||||
if (!context)
|
||||
context = mRoot;
|
||||
|
||||
XPathExpression* expr = xmlquery->GetResultsExpression();
|
||||
if (!expr)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<XPathResult> exprresults =
|
||||
expr->Evaluate(*context, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
|
||||
nullptr, rv);
|
||||
if (rv.Failed()) {
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
RefPtr<nsXULTemplateResultSetXML> results =
|
||||
new nsXULTemplateResultSetXML(xmlquery, exprresults.forget(),
|
||||
xmlquery->GetBindingSet());
|
||||
|
||||
results.forget(aResults);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::AddBinding(nsIDOMNode* aRuleNode,
|
||||
nsAtom* aVar,
|
||||
nsAtom* aRef,
|
||||
const nsAString& aExpr)
|
||||
{
|
||||
if (mGenerationStarted)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
RefPtr<nsXMLBindingSet> bindings = mRuleToBindingsMap.GetWeak(aRuleNode);
|
||||
if (!bindings) {
|
||||
bindings = new nsXMLBindingSet();
|
||||
mRuleToBindingsMap.Put(aRuleNode, bindings);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINode> ruleNode = do_QueryInterface(aRuleNode);
|
||||
|
||||
ErrorResult rv;
|
||||
nsAutoPtr<XPathExpression> compiledexpr;
|
||||
compiledexpr = CreateExpression(aExpr, ruleNode, rv);
|
||||
if (rv.Failed()) {
|
||||
rv.SuppressException();
|
||||
nsXULContentUtils::LogTemplateError(ERROR_TEMPLATE_BAD_BINDING_XPATH);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// aRef isn't currently used for XML query processors
|
||||
bindings->AddBinding(aVar, Move(compiledexpr));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::TranslateRef(nsISupports* aDatasource,
|
||||
const nsAString& aRefString,
|
||||
nsIXULTemplateResult** aRef)
|
||||
{
|
||||
*aRef = nullptr;
|
||||
|
||||
// the datasource is either a document or a DOM element
|
||||
nsCOMPtr<Element> rootElement;
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aDatasource);
|
||||
if (doc)
|
||||
rootElement = doc->GetRootElement();
|
||||
else
|
||||
rootElement = do_QueryInterface(aDatasource);
|
||||
|
||||
// if no root element, just return. The document may not have loaded yet
|
||||
if (!rootElement)
|
||||
return NS_OK;
|
||||
|
||||
RefPtr<nsXULTemplateResultXML> result = new nsXULTemplateResultXML(nullptr, rootElement, nullptr);
|
||||
result.forget(aRef);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::CompareResults(nsIXULTemplateResult* aLeft,
|
||||
nsIXULTemplateResult* aRight,
|
||||
nsAtom* aVar,
|
||||
uint32_t aSortHints,
|
||||
int32_t* aResult)
|
||||
{
|
||||
*aResult = 0;
|
||||
if (!aVar)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString leftVal;
|
||||
if (aLeft)
|
||||
aLeft->GetBindingFor(aVar, leftVal);
|
||||
|
||||
nsAutoString rightVal;
|
||||
if (aRight)
|
||||
aRight->GetBindingFor(aVar, rightVal);
|
||||
|
||||
*aResult = XULSortServiceImpl::CompareValues(leftVal, rightVal, aSortHints);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsXMLBindingSet*
|
||||
nsXULTemplateQueryProcessorXML::GetOptionalBindingsForRule(nsIDOMNode* aRuleNode)
|
||||
{
|
||||
return mRuleToBindingsMap.GetWeak(aRuleNode);
|
||||
}
|
||||
|
||||
XPathExpression*
|
||||
nsXULTemplateQueryProcessorXML::CreateExpression(const nsAString& aExpr,
|
||||
nsINode* aNode,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
return mEvaluator->CreateExpression(aExpr, aNode, aRv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateQueryProcessorXML::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_PRECONDITION(aEvent, "aEvent null");
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
|
||||
if (eventType.EqualsLiteral("load") && mTemplateBuilder) {
|
||||
NS_ASSERTION(mRequest, "request was not set");
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
if (NS_SUCCEEDED(mRequest->GetResponseXML(getter_AddRefs(doc))))
|
||||
mTemplateBuilder->SetDatasource(doc);
|
||||
|
||||
// to avoid leak. we don't need it after...
|
||||
mTemplateBuilder = nullptr;
|
||||
mRequest = nullptr;
|
||||
}
|
||||
else if (eventType.EqualsLiteral("error")) {
|
||||
mTemplateBuilder = nullptr;
|
||||
mRequest = nullptr;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,170 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateQueryProcessorXML_h__
|
||||
#define nsXULTemplateQueryProcessorXML_h__
|
||||
|
||||
#include "nsIXULTemplateBuilder.h"
|
||||
#include "nsIXULTemplateQueryProcessor.h"
|
||||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
#include "nsXMLBinding.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsIXMLHttpRequest.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/XPathEvaluator.h"
|
||||
#include "mozilla/dom/XPathResult.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorXML;
|
||||
|
||||
#define NS_IXMLQUERY_IID \
|
||||
{0x0358d692, 0xccce, 0x4a97, \
|
||||
{ 0xb2, 0x51, 0xba, 0x8f, 0x17, 0x0f, 0x3b, 0x6f }}
|
||||
|
||||
class nsXMLQuery final : 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
|
||||
nsAtom* GetMemberVariable() { return mMemberVariable; }
|
||||
|
||||
// return a weak reference to the expression used to generate results
|
||||
mozilla::dom::XPathExpression* GetResultsExpression()
|
||||
{ return mResultsExpr; }
|
||||
|
||||
// return a weak reference to the additional required bindings
|
||||
nsXMLBindingSet* GetBindingSet() { return mRequiredBindings; }
|
||||
|
||||
// add a required binding for the query
|
||||
void
|
||||
AddBinding(nsAtom* aVar, nsAutoPtr<mozilla::dom::XPathExpression>&& aExpr)
|
||||
{
|
||||
if (!mRequiredBindings) {
|
||||
mRequiredBindings = new nsXMLBindingSet();
|
||||
}
|
||||
|
||||
mRequiredBindings->AddBinding(aVar, mozilla::Move(aExpr));
|
||||
}
|
||||
|
||||
nsXMLQuery(nsXULTemplateQueryProcessorXML* aProcessor,
|
||||
nsAtom* aMemberVariable,
|
||||
nsAutoPtr<mozilla::dom::XPathExpression>&& aResultsExpr)
|
||||
: mProcessor(aProcessor),
|
||||
mMemberVariable(aMemberVariable),
|
||||
mResultsExpr(aResultsExpr)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
~nsXMLQuery() {}
|
||||
|
||||
nsXULTemplateQueryProcessorXML* mProcessor;
|
||||
|
||||
RefPtr<nsAtom> mMemberVariable;
|
||||
|
||||
nsAutoPtr<mozilla::dom::XPathExpression> mResultsExpr;
|
||||
|
||||
RefPtr<nsXMLBindingSet> mRequiredBindings;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsXMLQuery, NS_IXMLQUERY_IID)
|
||||
|
||||
class nsXULTemplateResultSetXML final : public nsISimpleEnumerator
|
||||
{
|
||||
private:
|
||||
|
||||
// reference back to the query
|
||||
nsCOMPtr<nsXMLQuery> mQuery;
|
||||
|
||||
// the binding set created from <assign> nodes
|
||||
RefPtr<nsXMLBindingSet> mBindingSet;
|
||||
|
||||
// set of results contained in this enumerator
|
||||
RefPtr<mozilla::dom::XPathResult> mResults;
|
||||
|
||||
// current position within the list of results
|
||||
uint32_t mPosition;
|
||||
|
||||
~nsXULTemplateResultSetXML() {}
|
||||
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator interface
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsXULTemplateResultSetXML(nsXMLQuery* aQuery,
|
||||
already_AddRefed<mozilla::dom::XPathResult> aResults,
|
||||
nsXMLBindingSet* aBindingSet)
|
||||
: mQuery(aQuery),
|
||||
mBindingSet(aBindingSet),
|
||||
mResults(aResults),
|
||||
mPosition(0)
|
||||
{}
|
||||
};
|
||||
|
||||
class nsXULTemplateQueryProcessorXML final : public nsIXULTemplateQueryProcessor,
|
||||
public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
|
||||
nsXULTemplateQueryProcessorXML()
|
||||
: mGenerationStarted(false)
|
||||
{}
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateQueryProcessorXML,
|
||||
nsIXULTemplateQueryProcessor)
|
||||
|
||||
// nsIXULTemplateQueryProcessor interface
|
||||
NS_DECL_NSIXULTEMPLATEQUERYPROCESSOR
|
||||
|
||||
// nsIDOMEventListener interface
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
nsXMLBindingSet*
|
||||
GetOptionalBindingsForRule(nsIDOMNode* aRuleNode);
|
||||
|
||||
// create an XPath expression from aExpr, using aNode for
|
||||
// resolving namespaces
|
||||
mozilla::dom::XPathExpression*
|
||||
CreateExpression(const nsAString& aExpr,
|
||||
nsINode* aNode,
|
||||
mozilla::ErrorResult& aRv);
|
||||
|
||||
private:
|
||||
|
||||
~nsXULTemplateQueryProcessorXML() {}
|
||||
|
||||
bool mGenerationStarted;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, nsXMLBindingSet> mRuleToBindingsMap;
|
||||
|
||||
nsCOMPtr<mozilla::dom::Element> mRoot;
|
||||
|
||||
RefPtr<mozilla::dom::XPathEvaluator> mEvaluator;
|
||||
|
||||
nsCOMPtr<nsIXULTemplateBuilder> mTemplateBuilder;
|
||||
|
||||
nsCOMPtr<nsIXMLHttpRequest> mRequest;
|
||||
};
|
||||
|
||||
|
||||
#endif // nsXULTemplateQueryProcessorXML_h__
|
@ -1,208 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULTemplateResultRDF.h"
|
||||
#include "nsXULContentUtils.h"
|
||||
|
||||
// XXXndeakin for some reason, making this class have classinfo breaks trees.
|
||||
//#include "nsIDOMClassInfo.h"
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(nsXULTemplateResultRDF, mQuery)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXULTemplateResultRDF)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXULTemplateResult)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsXULTemplateResultRDF)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsXULTemplateResultRDF)
|
||||
|
||||
nsXULTemplateResultRDF::nsXULTemplateResultRDF(nsIRDFResource* aNode)
|
||||
: mQuery(nullptr),
|
||||
mNode(aNode)
|
||||
{
|
||||
}
|
||||
|
||||
nsXULTemplateResultRDF::nsXULTemplateResultRDF(nsRDFQuery* aQuery,
|
||||
const Instantiation& aInst,
|
||||
nsIRDFResource *aNode)
|
||||
: mQuery(aQuery),
|
||||
mNode(aNode),
|
||||
mInst(aInst)
|
||||
{
|
||||
}
|
||||
|
||||
nsXULTemplateResultRDF::~nsXULTemplateResultRDF()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetIsContainer(bool* aIsContainer)
|
||||
{
|
||||
*aIsContainer = false;
|
||||
|
||||
if (mNode) {
|
||||
nsXULTemplateQueryProcessorRDF* processor = GetProcessor();
|
||||
if (processor)
|
||||
return processor->CheckContainer(mNode, aIsContainer);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetIsEmpty(bool* aIsEmpty)
|
||||
{
|
||||
*aIsEmpty = true;
|
||||
|
||||
if (mNode) {
|
||||
nsXULTemplateQueryProcessorRDF* processor = GetProcessor();
|
||||
if (processor)
|
||||
return processor->CheckEmpty(mNode, aIsEmpty);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetMayProcessChildren(bool* aMayProcessChildren)
|
||||
{
|
||||
// RDF always allows recursion
|
||||
*aMayProcessChildren = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetId(nsAString& aId)
|
||||
{
|
||||
if (! mNode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
const char* uri;
|
||||
mNode->GetValueConst(&uri);
|
||||
|
||||
CopyUTF8toUTF16(uri, aId);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetResource(nsIRDFResource** aResource)
|
||||
{
|
||||
*aResource = mNode;
|
||||
NS_IF_ADDREF(*aResource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Truncate();
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* processor = GetProcessor();
|
||||
if (processor) {
|
||||
bool found;
|
||||
rv = processor->CheckIsSeparator(mNode, &found);
|
||||
if (NS_SUCCEEDED(rv) && found)
|
||||
aType.AssignLiteral("separator");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetBindingFor(nsAtom* aVar, nsAString& aValue)
|
||||
{
|
||||
nsCOMPtr<nsIRDFNode> val;
|
||||
GetAssignment(aVar, getter_AddRefs(val));
|
||||
|
||||
return nsXULContentUtils::GetTextForNode(val, aValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::GetBindingObjectFor(nsAtom* aVar, nsISupports** aValue)
|
||||
{
|
||||
GetAssignment(aVar, (nsIRDFNode **)aValue);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::RuleMatched(nsISupports* aQuery, nsIDOMNode* aRuleNode)
|
||||
{
|
||||
// when a rule matches, set the bindings that must be used.
|
||||
nsXULTemplateQueryProcessorRDF* processor = GetProcessor();
|
||||
if (processor) {
|
||||
RDFBindingSet* bindings = processor->GetBindingsForRule(aRuleNode);
|
||||
if (bindings) {
|
||||
nsresult rv = mBindingValues.SetBindingSet(bindings);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
bindings->AddDependencies(mNode, this);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultRDF::HasBeenRemoved()
|
||||
{
|
||||
// when a result is no longer used, clean up the dependencies and
|
||||
// memory elements that refer to it
|
||||
mBindingValues.RemoveDependencies(mNode, this);
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* processor = GetProcessor();
|
||||
if (processor)
|
||||
processor->RemoveMemoryElements(mInst, this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXULTemplateResultRDF::GetAssignment(nsAtom* aVar, nsIRDFNode** aValue)
|
||||
{
|
||||
// look up a variable in the assignments map
|
||||
*aValue = nullptr;
|
||||
mInst.mAssignments.GetAssignmentFor(aVar, aValue);
|
||||
|
||||
// if not found, look up the variable in the bindings
|
||||
if (! *aValue)
|
||||
mBindingValues.GetAssignmentFor(this, aVar, aValue);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
nsXULTemplateResultRDF::SyncAssignments(nsIRDFResource* aSubject,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsIRDFNode* aTarget)
|
||||
{
|
||||
// synchronize the bindings when an assertion is added or removed
|
||||
RDFBindingSet* bindingset = mBindingValues.GetBindingSet();
|
||||
if (bindingset) {
|
||||
return bindingset->SyncAssignments(aSubject, aPredicate, aTarget,
|
||||
(aSubject == mNode) ? mQuery->GetMemberVariable() : nullptr,
|
||||
this, mBindingValues);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
nsXULTemplateResultRDF::HasMemoryElement(const MemoryElement& aMemoryElement)
|
||||
{
|
||||
MemoryElementSet::ConstIterator last = mInst.mSupport.Last();
|
||||
for (MemoryElementSet::ConstIterator element = mInst.mSupport.First();
|
||||
element != last; ++element) {
|
||||
if ((*element).Equals(aMemoryElement))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateResultRDF_h__
|
||||
#define nsXULTemplateResultRDF_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
#include "nsRDFQuery.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "nsRDFBinding.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
/**
|
||||
* A single result of a query on an RDF graph
|
||||
*/
|
||||
class nsXULTemplateResultRDF final : public nsIXULTemplateResult
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(nsXULTemplateResultRDF)
|
||||
|
||||
NS_DECL_NSIXULTEMPLATERESULT
|
||||
|
||||
explicit nsXULTemplateResultRDF(nsIRDFResource* aNode);
|
||||
|
||||
nsXULTemplateResultRDF(nsRDFQuery* aQuery,
|
||||
const Instantiation& aInst,
|
||||
nsIRDFResource* aNode);
|
||||
|
||||
nsITemplateRDFQuery* Query() { return mQuery; }
|
||||
|
||||
nsXULTemplateQueryProcessorRDF* GetProcessor()
|
||||
{
|
||||
return (mQuery ? mQuery->Processor() : nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of a variable, first by looking in the assignments and
|
||||
* then the bindings
|
||||
*/
|
||||
void
|
||||
GetAssignment(nsAtom* aVar, nsIRDFNode** aValue);
|
||||
|
||||
/**
|
||||
* Synchronize the bindings after a change in the RDF graph. Bindings that
|
||||
* would be affected will be assigned appropriately based on the change.
|
||||
*/
|
||||
bool
|
||||
SyncAssignments(nsIRDFResource* aSubject,
|
||||
nsIRDFResource* aPredicate,
|
||||
nsIRDFNode* aTarget);
|
||||
|
||||
/**
|
||||
* Return true if the result has an instantiation involving a particular
|
||||
* memory element.
|
||||
*/
|
||||
bool
|
||||
HasMemoryElement(const MemoryElement& aMemoryElement);
|
||||
|
||||
protected:
|
||||
~nsXULTemplateResultRDF();
|
||||
|
||||
// query that generated the result
|
||||
nsCOMPtr<nsITemplateRDFQuery> mQuery;
|
||||
|
||||
// resource node
|
||||
nsCOMPtr<nsIRDFResource> mNode;
|
||||
|
||||
// data computed from query
|
||||
Instantiation mInst;
|
||||
|
||||
// extra assignments made by rules (<binding> tags)
|
||||
nsBindingValues mBindingValues;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateResultRDF_h__
|
@ -1,82 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsXULTemplateResultSetRDF.h"
|
||||
#include "nsXULTemplateQueryProcessorRDF.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateResultSetRDF, nsISimpleEnumerator)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetRDF::HasMoreElements(bool *aResult)
|
||||
{
|
||||
*aResult = true;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> node;
|
||||
|
||||
if (! mInstantiations || ! mQuery) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mCheckedNext) {
|
||||
if (!mCurrent || mCurrent == &(mInstantiations->mHead))
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mCheckedNext = true;
|
||||
|
||||
do {
|
||||
if (mCurrent) {
|
||||
mCurrent = mCurrent->mNext;
|
||||
if (mCurrent == &(mInstantiations->mHead)) {
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
else {
|
||||
*aResult = ! mInstantiations->Empty();
|
||||
if (*aResult)
|
||||
mCurrent = mInstantiations->mHead.mNext;
|
||||
}
|
||||
|
||||
// get the value of the member variable. If it is not set, skip
|
||||
// the result and move on to the next result
|
||||
if (mCurrent) {
|
||||
mCurrent->mInstantiation.mAssignments.
|
||||
GetAssignmentFor(mQuery->mMemberVariable, getter_AddRefs(node));
|
||||
}
|
||||
|
||||
// only resources may be used as results
|
||||
mResource = do_QueryInterface(node);
|
||||
} while (! mResource);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultSetRDF::GetNext(nsISupports **aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (!mCurrent || !mCheckedNext)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
RefPtr<nsXULTemplateResultRDF> nextresult =
|
||||
new nsXULTemplateResultRDF(mQuery, mCurrent->mInstantiation, mResource);
|
||||
if (!nextresult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// add the supporting memory elements to the processor's map. These are
|
||||
// used to remove the results when an assertion is removed from the graph
|
||||
mProcessor->AddMemoryElements(mCurrent->mInstantiation, nextresult);
|
||||
|
||||
mCheckedNext = false;
|
||||
|
||||
nextresult.forget(aResult);
|
||||
|
||||
return NS_OK;
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateResultSetRDF_h__
|
||||
#define nsXULTemplateResultSetRDF_h__
|
||||
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsRuleNetwork.h"
|
||||
#include "nsRDFQuery.h"
|
||||
#include "nsXULTemplateResultRDF.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
class nsXULTemplateQueryProcessorRDF;
|
||||
class nsXULTemplateResultRDF;
|
||||
|
||||
/**
|
||||
* An enumerator used to iterate over a set of results.
|
||||
*/
|
||||
class nsXULTemplateResultSetRDF final : public nsISimpleEnumerator
|
||||
{
|
||||
private:
|
||||
nsXULTemplateQueryProcessorRDF* mProcessor;
|
||||
|
||||
nsRDFQuery* mQuery;
|
||||
|
||||
const InstantiationSet* mInstantiations;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> mResource;
|
||||
|
||||
InstantiationSet::List *mCurrent;
|
||||
|
||||
bool mCheckedNext;
|
||||
|
||||
~nsXULTemplateResultSetRDF()
|
||||
{
|
||||
delete mInstantiations;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsISimpleEnumerator interface
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
nsXULTemplateResultSetRDF(nsXULTemplateQueryProcessorRDF *aProcessor,
|
||||
nsRDFQuery* aQuery,
|
||||
const InstantiationSet* aInstantiations)
|
||||
: mProcessor(aProcessor),
|
||||
mQuery(aQuery),
|
||||
mInstantiations(aInstantiations),
|
||||
mCurrent(nullptr),
|
||||
mCheckedNext(false)
|
||||
{ }
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateResultSetRDF_h__
|
@ -1,126 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXULTemplateResultStorage.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateResultStorage, nsIXULTemplateResult)
|
||||
|
||||
nsXULTemplateResultStorage::nsXULTemplateResultStorage(nsXULTemplateResultSetStorage* aResultSet)
|
||||
{
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
nsCOMPtr<nsIRDFService> rdfService = do_GetService(kRDFServiceCID);
|
||||
rdfService->GetAnonymousResource(getter_AddRefs(mNode));
|
||||
mResultSet = aResultSet;
|
||||
if (aResultSet) {
|
||||
mResultSet->FillColumnValues(mValues);
|
||||
}
|
||||
}
|
||||
|
||||
nsXULTemplateResultStorage::~nsXULTemplateResultStorage()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetIsContainer(bool* aIsContainer)
|
||||
{
|
||||
*aIsContainer = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetIsEmpty(bool* aIsEmpty)
|
||||
{
|
||||
*aIsEmpty = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetMayProcessChildren(bool* aMayProcessChildren)
|
||||
{
|
||||
*aMayProcessChildren = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetId(nsAString& aId)
|
||||
{
|
||||
const char* uri = nullptr;
|
||||
mNode->GetValueConst(&uri);
|
||||
|
||||
aId.Assign(NS_ConvertUTF8toUTF16(uri));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetResource(nsIRDFResource** aResource)
|
||||
{
|
||||
*aResource = mNode;
|
||||
NS_IF_ADDREF(*aResource);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetBindingFor(nsAtom* aVar, nsAString& aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aVar);
|
||||
|
||||
aValue.Truncate();
|
||||
if (!mResultSet) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
int32_t idx = mResultSet->GetColumnIndex(aVar);
|
||||
if (idx < 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIVariant * value = mValues[idx];
|
||||
if (value) {
|
||||
value->GetAsAString(aValue);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::GetBindingObjectFor(nsAtom* aVar, nsISupports** aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aVar);
|
||||
|
||||
if (mResultSet) {
|
||||
int32_t idx = mResultSet->GetColumnIndex(aVar);
|
||||
if (idx >= 0) {
|
||||
*aValue = mValues[idx];
|
||||
NS_IF_ADDREF(*aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
*aValue = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::RuleMatched(nsISupports* aQuery, nsIDOMNode* aRuleNode)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultStorage::HasBeenRemoved()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateResultStorage_h__
|
||||
#define nsXULTemplateResultStorage_h__
|
||||
|
||||
#include "nsXULTemplateQueryProcessorStorage.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
/**
|
||||
* A single result of a query from mozstorage
|
||||
*/
|
||||
class nsXULTemplateResultStorage final : public nsIXULTemplateResult
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIXULTEMPLATERESULT
|
||||
|
||||
explicit nsXULTemplateResultStorage(nsXULTemplateResultSetStorage* aResultSet);
|
||||
|
||||
protected:
|
||||
|
||||
~nsXULTemplateResultStorage();
|
||||
|
||||
RefPtr<nsXULTemplateResultSetStorage> mResultSet;
|
||||
|
||||
nsCOMArray<nsIVariant> mValues;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> mNode;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateResultStorage_h__
|
@ -1,189 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIContent.h"
|
||||
|
||||
#include "nsIRDFService.h"
|
||||
|
||||
#include "nsXULTemplateResultXML.h"
|
||||
#include "nsXMLBinding.h"
|
||||
|
||||
static uint32_t sTemplateId = 0;
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXULTemplateResultXML, nsIXULTemplateResult)
|
||||
|
||||
nsXULTemplateResultXML::nsXULTemplateResultXML(nsXMLQuery* aQuery,
|
||||
nsIContent* aNode,
|
||||
nsXMLBindingSet* aBindings)
|
||||
: mQuery(aQuery), mNode(aNode)
|
||||
{
|
||||
// If the node has an id, create the uri from it. Otherwise, there isn't
|
||||
// anything to identify the node with so just use a somewhat random number.
|
||||
RefPtr<nsAtom> id = mNode->GetID();
|
||||
if (id) {
|
||||
nsCOMPtr<nsIURI> uri = mNode->GetBaseURI();
|
||||
nsAutoCString spec;
|
||||
uri->GetSpec(spec);
|
||||
|
||||
mId = NS_ConvertUTF8toUTF16(spec);
|
||||
|
||||
nsAutoString idstr;
|
||||
id->ToString(idstr);
|
||||
mId += NS_LITERAL_STRING("#") + idstr;
|
||||
}
|
||||
else {
|
||||
nsAutoString rowid(NS_LITERAL_STRING("row"));
|
||||
rowid.AppendInt(++sTemplateId);
|
||||
mId.Assign(rowid);
|
||||
}
|
||||
|
||||
if (aBindings)
|
||||
mRequiredValues.SetBindingSet(aBindings);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetIsContainer(bool* aIsContainer)
|
||||
{
|
||||
// a node is considered a container if it has children
|
||||
*aIsContainer = mNode && mNode->HasChildNodes();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetIsEmpty(bool* aIsEmpty)
|
||||
{
|
||||
// a node is considered empty if it has no elements as children
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mNode);
|
||||
if (content) {
|
||||
for (nsIContent* child = content->GetFirstChild();
|
||||
child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (child->IsElement()) {
|
||||
*aIsEmpty = false;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*aIsEmpty = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetMayProcessChildren(bool* aMayProcessChildren)
|
||||
{
|
||||
*aMayProcessChildren = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetId(nsAString& aId)
|
||||
{
|
||||
aId = mId;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetResource(nsIRDFResource** aResource)
|
||||
{
|
||||
*aResource = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetType(nsAString& aType)
|
||||
{
|
||||
aType.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::GetBindingFor(nsAtom* aVar, nsAString& aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aVar);
|
||||
|
||||
// get the position of the atom in the variables table
|
||||
nsXMLBinding* binding;
|
||||
|
||||
int32_t 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(nsAtom* aVar, nsISupports** aValue)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aVar);
|
||||
|
||||
nsXMLBinding* binding;
|
||||
nsCOMPtr<nsISupports> node;
|
||||
|
||||
if (mQuery && aVar == mQuery->GetMemberVariable()) {
|
||||
node = mNode;
|
||||
}
|
||||
else {
|
||||
int32_t idx = mRequiredValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx > 0) {
|
||||
node = mRequiredValues.GetNodeAssignmentFor(this, binding, idx);
|
||||
}
|
||||
else {
|
||||
idx = mOptionalValues.LookupTargetIndex(aVar, &binding);
|
||||
if (idx > 0) {
|
||||
node = mOptionalValues.GetNodeAssignmentFor(this, binding, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.forget(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() :
|
||||
nullptr;
|
||||
if (processor) {
|
||||
nsXMLBindingSet* bindings =
|
||||
processor->GetOptionalBindingsForRule(aRuleNode);
|
||||
if (bindings)
|
||||
mOptionalValues.SetBindingSet(bindings);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULTemplateResultXML::HasBeenRemoved()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTemplateResultXML_h__
|
||||
#define nsXULTemplateResultXML_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsIRDFResource.h"
|
||||
#include "nsXULTemplateQueryProcessorXML.h"
|
||||
#include "nsIXULTemplateResult.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
/**
|
||||
* An single result of an query
|
||||
*/
|
||||
class nsXULTemplateResultXML final : public nsIXULTemplateResult
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_DECL_NSIXULTEMPLATERESULT
|
||||
|
||||
nsXULTemplateResultXML(nsXMLQuery* aQuery,
|
||||
nsIContent* aNode,
|
||||
nsXMLBindingSet* aBindings);
|
||||
|
||||
nsIContent* Node()
|
||||
{
|
||||
return mNode;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
~nsXULTemplateResultXML() {}
|
||||
|
||||
// ID used for persisting data. It is constructed using the mNode's
|
||||
// base uri plus the node's id to form 'baseuri#id'. If the node has no
|
||||
// id, then an id of the form 'row<some number>' is generated. In the
|
||||
// latter case, persistence will not work as there won't be a unique id.
|
||||
nsAutoString mId;
|
||||
|
||||
// query that generated the result
|
||||
nsCOMPtr<nsXMLQuery> mQuery;
|
||||
|
||||
// context node in datasource
|
||||
nsCOMPtr<nsIContent> mNode;
|
||||
|
||||
// assignments in query
|
||||
nsXMLBindingValues mRequiredValues;
|
||||
|
||||
// extra assignments made by rules (<binding> tags)
|
||||
nsXMLBindingValues mOptionalValues;
|
||||
};
|
||||
|
||||
#endif // nsXULTemplateResultXML_h__
|
File diff suppressed because it is too large
Load Diff
@ -1,322 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef nsXULTreeBuilder_h__
|
||||
#define nsXULTreeBuilder_h__
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsITreeView.h"
|
||||
#include "nsTreeRows.h"
|
||||
#include "nsXULTemplateBuilder.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIRDFResource;
|
||||
class nsITreeSelection;
|
||||
class nsIXULStore;
|
||||
class nsIXULTemplateResult;
|
||||
class nsTreeColumn;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class DataTransfer;
|
||||
class TreeBoxObject;
|
||||
class XULTreeBuilderObserver;
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
* A XUL template builder that serves as an tree view, allowing
|
||||
* (pretty much) arbitrary RDF to be presented in an tree.
|
||||
*/
|
||||
class nsXULTreeBuilder : public nsXULTemplateBuilder,
|
||||
public nsIXULTreeBuilder,
|
||||
public nsINativeTreeView
|
||||
{
|
||||
public:
|
||||
explicit nsXULTreeBuilder(Element* aElement);
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsXULTreeBuilder,
|
||||
nsXULTemplateBuilder)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
already_AddRefed<nsIRDFResource>
|
||||
GetResourceAtIndex(int32_t aIndex, mozilla::ErrorResult& aError);
|
||||
int32_t GetIndexOfResource(nsIRDFResource* aResource,
|
||||
mozilla::ErrorResult& aError);
|
||||
void AddObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
|
||||
void RemoveObserver(mozilla::dom::XULTreeBuilderObserver& aObserver);
|
||||
void Sort(Element&);
|
||||
|
||||
int32_t RowCount()
|
||||
{
|
||||
return mRows.Count();
|
||||
}
|
||||
nsITreeSelection* GetSelection()
|
||||
{
|
||||
return mSelection;
|
||||
}
|
||||
void SetSelection(nsITreeSelection* aSelection,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetRowProperties(int32_t aRow, nsAString& aProperties,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetCellProperties(int32_t aRow, nsTreeColumn& aColumn,
|
||||
nsAString& aProperties, mozilla::ErrorResult& aError);
|
||||
void GetColumnProperties(nsTreeColumn& aColumn, nsAString& aProperties)
|
||||
{
|
||||
}
|
||||
bool IsContainer(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
bool IsContainerOpen(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
bool IsContainerEmpty(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
bool IsSeparator(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
bool IsSorted()
|
||||
{
|
||||
return mSortVariable != nullptr;
|
||||
}
|
||||
bool CanDrop(int32_t aRow, int32_t aOrientation,
|
||||
mozilla::dom::DataTransfer* aDataTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
void Drop(int32_t aRow, int32_t aOrientation,
|
||||
mozilla::dom::DataTransfer* aDataTransfer,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t GetParentIndex(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
bool HasNextSibling(int32_t aRow, int32_t aAfterIndex,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t GetLevel(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
void GetImageSrc(int32_t aRow, nsTreeColumn& aColumn, nsAString& aSrc,
|
||||
mozilla::ErrorResult& aError);
|
||||
int32_t GetProgressMode(int32_t aRow, nsTreeColumn& aColumn,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetCellValue(int32_t aRow, nsTreeColumn& aColumn, nsAString& aValue,
|
||||
mozilla::ErrorResult& aError);
|
||||
void GetCellText(int32_t aRow, nsTreeColumn& aColumn, nsAString& aText,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetTree(mozilla::dom::TreeBoxObject* aTree,
|
||||
mozilla::ErrorResult& aError);
|
||||
void ToggleOpenState(int32_t aRow, mozilla::ErrorResult& aError);
|
||||
void CycleHeader(nsTreeColumn& aColumn, mozilla::ErrorResult& aError);
|
||||
// XPCOM SelectionChanged() is OK
|
||||
void CycleCell(int32_t aRow, nsTreeColumn& aColumn);
|
||||
bool IsEditable(int32_t aRow, nsTreeColumn& aColumn,
|
||||
mozilla::ErrorResult& aError);
|
||||
bool IsSelectable(int32_t aRow, nsTreeColumn& aColumn,
|
||||
mozilla::ErrorResult& aError);
|
||||
void SetCellValue(int32_t aRow, nsTreeColumn& aColumn,
|
||||
const nsAString& aValue, mozilla::ErrorResult& aError)
|
||||
{
|
||||
}
|
||||
void SetCellText(int32_t aRow, nsTreeColumn& aColumn,
|
||||
const nsAString& aText, mozilla::ErrorResult& aError)
|
||||
{
|
||||
}
|
||||
void PerformAction(const nsAString& aAction);
|
||||
void PerformActionOnRow(const nsAString& aAction, int32_t aRow);
|
||||
void PerformActionOnCell(const nsAString& aAction, int32_t aRow,
|
||||
nsTreeColumn& aColumn);
|
||||
|
||||
using nsIXULTemplateBuilder::HasGeneratedContent;
|
||||
virtual bool HasGeneratedContent(nsIRDFResource* aResource,
|
||||
const nsAString& aTag,
|
||||
mozilla::ErrorResult& aError) override;
|
||||
|
||||
// nsIXULTreeBuilder
|
||||
NS_DECL_NSIXULTREEBUILDER
|
||||
|
||||
// nsITreeView
|
||||
NS_DECL_NSITREEVIEW
|
||||
// nsINativeTreeView: Untrusted code can use us
|
||||
NS_IMETHOD EnsureNative() override { return NS_OK; }
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
|
||||
|
||||
protected:
|
||||
friend struct ResultComparator;
|
||||
|
||||
~nsXULTreeBuilder();
|
||||
|
||||
/**
|
||||
* Uninitialize the template builder
|
||||
*/
|
||||
virtual void Uninit(bool aIsFinal) override;
|
||||
|
||||
/**
|
||||
* Get sort variables from the active <treecol>
|
||||
*/
|
||||
nsresult
|
||||
EnsureSortVariables();
|
||||
|
||||
virtual nsresult
|
||||
RebuildAll() override;
|
||||
|
||||
/**
|
||||
* Given a row, use the row's match to figure out the appropriate
|
||||
* <treerow> in the rule's <action>.
|
||||
*/
|
||||
nsresult
|
||||
GetTemplateActionRowFor(int32_t aRow, mozilla::dom::Element** aResult);
|
||||
|
||||
/**
|
||||
* Given a row and a column ID, use the row's match to figure out
|
||||
* the appropriate <treecell> in the rule's <action>.
|
||||
*/
|
||||
mozilla::dom::Element*
|
||||
GetTemplateActionCellFor(int32_t aRow, nsTreeColumn& aCol);
|
||||
|
||||
/**
|
||||
* Return the resource corresponding to a row in the tree.
|
||||
*/
|
||||
nsresult
|
||||
GetResourceFor(int32_t aRow, nsIRDFResource** aResource);
|
||||
|
||||
/**
|
||||
* Open a container row, inserting the container's children into
|
||||
* the view.
|
||||
*/
|
||||
nsresult
|
||||
OpenContainer(int32_t aIndex, nsIXULTemplateResult* aResult);
|
||||
|
||||
/**
|
||||
* Helper for OpenContainer, recursively open subtrees, remembering
|
||||
* persisted ``open'' state
|
||||
*/
|
||||
nsresult
|
||||
OpenSubtreeOf(nsTreeRows::Subtree* aSubtree,
|
||||
int32_t aIndex,
|
||||
nsIXULTemplateResult *aResult,
|
||||
int32_t* aDelta);
|
||||
|
||||
nsresult
|
||||
OpenSubtreeForQuerySet(nsTreeRows::Subtree* aSubtree,
|
||||
int32_t aIndex,
|
||||
nsIXULTemplateResult *aResult,
|
||||
nsTemplateQuerySet* aQuerySet,
|
||||
int32_t* aDelta,
|
||||
nsTArray<int32_t>& open);
|
||||
|
||||
/**
|
||||
* Close a container row, removing the container's childrem from
|
||||
* the view.
|
||||
*/
|
||||
nsresult
|
||||
CloseContainer(int32_t aIndex);
|
||||
|
||||
/**
|
||||
* Remove the matches for the rows in a subtree
|
||||
*/
|
||||
nsresult
|
||||
RemoveMatchesFor(nsTreeRows::Subtree& subtree);
|
||||
|
||||
/**
|
||||
* Helper method that determines if the specified container is open.
|
||||
*/
|
||||
bool
|
||||
IsContainerOpen(nsIXULTemplateResult* aResource);
|
||||
|
||||
/**
|
||||
* A sorting callback for NS_QuickSort().
|
||||
*/
|
||||
static int
|
||||
Compare(const void* aLeft, const void* aRight, void* aClosure);
|
||||
|
||||
/**
|
||||
* The real sort routine
|
||||
*/
|
||||
int32_t
|
||||
CompareResults(nsIXULTemplateResult* aLeft, nsIXULTemplateResult* aRight);
|
||||
|
||||
/**
|
||||
* Sort the specified subtree, and recursively sort any subtrees
|
||||
* beneath it.
|
||||
*/
|
||||
nsresult
|
||||
SortSubtree(nsTreeRows::Subtree* aSubtree);
|
||||
|
||||
// GetInsertionLocations, ReplaceMatch and SynchronizeResult are inherited
|
||||
// from nsXULTemplateBuilder
|
||||
|
||||
/**
|
||||
* Return true if the result can be inserted into the template as a new
|
||||
* row.
|
||||
*/
|
||||
bool
|
||||
GetInsertionLocations(nsIXULTemplateResult* aResult,
|
||||
nsCOMArray<Element>** aLocations) override;
|
||||
|
||||
/**
|
||||
* Implement result replacement
|
||||
*/
|
||||
virtual nsresult
|
||||
ReplaceMatch(nsIXULTemplateResult* aOldResult,
|
||||
nsTemplateMatch* aNewMatch,
|
||||
nsTemplateRule* aNewMatchRule,
|
||||
Element* aContext) override;
|
||||
|
||||
/**
|
||||
* Implement match synchronization
|
||||
*/
|
||||
virtual nsresult
|
||||
SynchronizeResult(nsIXULTemplateResult* aResult) override;
|
||||
|
||||
bool IsValidRowIndex(int32_t aRowIndex);
|
||||
|
||||
/**
|
||||
* The tree's box object, used to communicate with the front-end.
|
||||
*/
|
||||
nsCOMPtr<nsITreeBoxObject> mBoxObject;
|
||||
|
||||
/**
|
||||
* The tree's selection object.
|
||||
*/
|
||||
nsCOMPtr<nsITreeSelection> mSelection;
|
||||
|
||||
/**
|
||||
* The datasource that's used to persist open folder information
|
||||
*/
|
||||
nsCOMPtr<nsIRDFDataSource> mPersistStateStore;
|
||||
|
||||
/**
|
||||
* The rows in the view
|
||||
*/
|
||||
nsTreeRows mRows;
|
||||
|
||||
/**
|
||||
* The currently active sort variable
|
||||
*/
|
||||
RefPtr<nsAtom> mSortVariable;
|
||||
|
||||
enum Direction {
|
||||
eDirection_Descending = -1,
|
||||
eDirection_Natural = 0,
|
||||
eDirection_Ascending = +1
|
||||
};
|
||||
|
||||
/**
|
||||
* The currently active sort order
|
||||
*/
|
||||
Direction mSortDirection;
|
||||
|
||||
/*
|
||||
* Sort hints (compare case, etc)
|
||||
*/
|
||||
uint32_t mSortHints;
|
||||
|
||||
/**
|
||||
* The builder observers.
|
||||
*/
|
||||
nsTArray<nsCOMPtr<nsIXULTreeBuilderObserver>> mObservers;
|
||||
|
||||
/*
|
||||
* XUL store for holding open container state
|
||||
*/
|
||||
nsCOMPtr<nsIXULStore> mLocalStore;
|
||||
};
|
||||
|
||||
#endif // nsXULTreeBuilder_h__
|
@ -1,224 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:NC="http://home.netscape.com/NC-rdf#"
|
||||
xmlns:ANIMALS="http://www.some-fictitious-zoo.com/rdf#">
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/arachnids">
|
||||
<ANIMALS:name>Arachnids</ANIMALS:name>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/arachnids/tarantula" ANIMALS:specimens="3">
|
||||
<ANIMALS:name>Tarantula</ANIMALS:name>
|
||||
<ANIMALS:species>Avicularia avicularia</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/birds">
|
||||
<ANIMALS:name>Birds</ANIMALS:name>
|
||||
<ANIMALS:keeper resource="http://www.some-fictitious-zoo.com/humans/sarah"/>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/emu" ANIMALS:specimens="12">
|
||||
<ANIMALS:name>Emu</ANIMALS:name>
|
||||
<ANIMALS:species>Dromaius novaehollandiae</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/barnowl" ANIMALS:specimens="4">
|
||||
<ANIMALS:name>Barn Owl</ANIMALS:name>
|
||||
<ANIMALS:species>Tyto alba</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/birds/raven" ANIMALS:specimens="0">
|
||||
<ANIMALS:name>Raven</ANIMALS:name>
|
||||
<ANIMALS:species>Corvus corax</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/crustaceans">
|
||||
<ANIMALS:name>Crustaceans</ANIMALS:name>
|
||||
<ANIMALS:keeper resource="http://www.some-fictitious-zoo.com/humans/robert"/>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/fish">
|
||||
<ANIMALS:name>Fish</ANIMALS:name>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/fish/cod" ANIMALS:specimens="0">
|
||||
<ANIMALS:name>Cod</ANIMALS:name>
|
||||
<ANIMALS:species>Gadus morhua</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/fish/swordfish" ANIMALS:specimens="3">
|
||||
<ANIMALS:name>Swordfish</ANIMALS:name>
|
||||
<ANIMALS:species>Xiphias gladius</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/mammals">
|
||||
<ANIMALS:name>Mammals</ANIMALS:name>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/lion">
|
||||
<ANIMALS:name>Lion</ANIMALS:name>
|
||||
<ANIMALS:species>Panthera leo</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">4</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>4</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/hippopotamus">
|
||||
<ANIMALS:name>HIPPOPOTAMUS</ANIMALS:name>
|
||||
<ANIMALS:species>Hippopotamus amphibius</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">2</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>2</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/africanelephant">
|
||||
<ANIMALS:name>African Elephant</ANIMALS:name>
|
||||
<ANIMALS:species>Loxodonta africana</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">14</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>14</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/llama">
|
||||
<ANIMALS:name>LLAMA</ANIMALS:name>
|
||||
<ANIMALS:species>Lama glama</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">5</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>5</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/polarbear">
|
||||
<ANIMALS:name>Polar Bear</ANIMALS:name>
|
||||
<ANIMALS:species>Thalarctos maritimus</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">20</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>20</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/aardvark">
|
||||
<ANIMALS:name>aardvark</ANIMALS:name>
|
||||
<ANIMALS:species>Orycteropus afer</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">2</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>2</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/ninebandedarmadillo">
|
||||
<ANIMALS:name>Nine-banded Armadillo</ANIMALS:name>
|
||||
<ANIMALS:species>Dasypus novemcinctus</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">1</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>1</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/mammals/gorilla">
|
||||
<ANIMALS:name>Gorilla</ANIMALS:name>
|
||||
<ANIMALS:species>Gorilla gorilla</ANIMALS:species>
|
||||
<ANIMALS:specimens NC:parseType="Integer">7</ANIMALS:specimens>
|
||||
<ANIMALS:specimensAsString>7</ANIMALS:specimensAsString>
|
||||
</RDF:Description>
|
||||
|
||||
<ANIMALS:Class RDF:about="http://www.some-fictitious-zoo.com/reptiles">
|
||||
<ANIMALS:name>Reptiles</ANIMALS:name>
|
||||
<ANIMALS:keeper resource="http://www.some-fictitious-zoo.com/humans/robert"/>
|
||||
</ANIMALS:Class>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/reptiles/anaconda" ANIMALS:specimens="1">
|
||||
<ANIMALS:name>Anaconda</ANIMALS:name>
|
||||
<ANIMALS:species>Eunectes murinus</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/reptiles/chameleon" ANIMALS:specimens="2">
|
||||
<ANIMALS:name>Chameleon</ANIMALS:name>
|
||||
<ANIMALS:species>Chamaeleo chamaelon</ANIMALS:species>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/some-animals" ANIMALS:name="Zoo Animals">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/all-animals" ANIMALS:name="Zoo Animals">
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/arachnids">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||
</RDF:Seq>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/birds">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/emu"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/barnowl"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/raven"/>
|
||||
</RDF:Seq>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/crustaceans"/>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/fish">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/fish/cod"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/fish/swordfish"/>
|
||||
</RDF:Seq>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/mammals">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/lion"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/hippopotamus"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/africanelephant"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/llama"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/polarbear"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/aardvark"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/ninebandedarmadillo"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/gorilla"/>
|
||||
</RDF:Seq>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/reptiles">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/reptiles/anaconda"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/reptiles/chameleon"/>
|
||||
</RDF:Seq>
|
||||
</RDF:li>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/humans" ANIMALS:name="Humans">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/humans/sarah"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/humans/robert"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/sarahs-pets" ANIMALS:name="Sarah's Pets">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/emu"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/roberts-pets" ANIMALS:name="Robert's Pets">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/reptiles/chameleon"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals/llama"/>
|
||||
</RDF:Seq>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/humans/sarah" ANIMALS:name="Sarah">
|
||||
<ANIMALS:pets resource="http://www.some-fictitious-zoo.com/sarahs-pets"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/birds/emu"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/mammals/polarbear"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||
<ANIMALS:description>
|
||||
Sarah became caretaker of the Fictitious Zoo's emu exhibit in 2001. With so
|
||||
many emus living there, she has a lot to do!
|
||||
</ANIMALS:description>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Description RDF:about="http://www.some-fictitious-zoo.com/humans/robert" ANIMALS:name="Robert">
|
||||
<ANIMALS:pets resource="http://www.some-fictitious-zoo.com/roberts-pets"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/arachnids/tarantula"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/reptiles/anaconda"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/reptiles/chameleon"/>
|
||||
<ANIMALS:favoriteAnimal resource="http://www.some-fictitious-zoo.com/mammals/africanelephant"/>
|
||||
<ANIMALS:description>
|
||||
Robert helps visitors to the Fictitious Zoo's reptile pavilion learn
|
||||
more about some of the more unusual creatures that live there.
|
||||
</ANIMALS:description>
|
||||
<ANIMALS:lastName>Sanderson</ANIMALS:lastName>
|
||||
</RDF:Description>
|
||||
|
||||
<RDF:Seq RDF:about="http://www.some-fictitious-zoo.com/marked" ANIMALS:name="Marked">
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/humans/sarah"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/mammals"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/crustaceans"/>
|
||||
<RDF:li RDF:resource="http://www.some-fictitious-zoo.com/birds/emu"/>
|
||||
</RDF:Seq>
|
||||
|
||||
</RDF:RDF>
|
Binary file not shown.
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE zoo [
|
||||
<!ATTLIST species id ID #REQUIRED>
|
||||
]>
|
||||
|
||||
<zoo>
|
||||
<class>
|
||||
<name>Reptiles</name>
|
||||
<species id="Chamaeleo-chamaelon" name="Chameleon" specimens="2"/>
|
||||
</class>
|
||||
<class>
|
||||
<name>Birds</name>
|
||||
<species id="Dromaius-novaehollandiae" name="Emu" specimens="12"/>
|
||||
<species id="Tyto-alba" name="Barn Owl" specimens="4"/>
|
||||
<species id="Corvus-corax" name="Raven" specimens="0"/>
|
||||
<location>Aviary</location>
|
||||
</class>
|
||||
</zoo>
|
@ -1,263 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:row="http://dummy/rdf#" xmlns:NC="http://home.netscape.com/NC-rdf#">
|
||||
<RDF:Bag about="urn:data:row">
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111110</row:id>
|
||||
<row:title>FILE 1 -- A</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111111</row:id>
|
||||
<row:title>FILE 1 -- B</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111110</row:id>
|
||||
<row:title>FILE 1 -- C</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111111</row:id>
|
||||
<row:title>FILE 1 -- D</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111112</row:id>
|
||||
<row:title>FILE 1 -- E</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111110</row:id>
|
||||
<row:title>FILE 1 -- F</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111114</row:id>
|
||||
<row:title>FILE 1 -- G</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111111</row:id>
|
||||
<row:title>FILE 1 -- H</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111118</row:id>
|
||||
<row:title>FILE 1 -- I</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111116</row:id>
|
||||
<row:title>FILE 1 -- J</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111110</row:id>
|
||||
<row:title>FILE 1 -- K</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111119</row:id>
|
||||
<row:title>FILE 1 -- L</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111116</row:id>
|
||||
<row:title>FILE 1 -- M</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111111</row:id>
|
||||
<row:title>FILE 1 -- N</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111113</row:id>
|
||||
<row:title>FILE 1 -- O</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111111</row:id>
|
||||
<row:title>FILE 1 -- P</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111117</row:id>
|
||||
<row:title>FILE 1 -- Q</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111110</row:id>
|
||||
<row:title>FILE 1 -- R</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111113</row:id>
|
||||
<row:title>FILE 1 -- S</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111112</row:id>
|
||||
<row:title>FILE 1 -- T</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111116</row:id>
|
||||
<row:title>FILE 1 -- U</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111111</row:id>
|
||||
<row:title>FILE 1 -- V</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111121</row:id>
|
||||
<row:title>FILE 1 -- W</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111114</row:id>
|
||||
<row:title>FILE 1 -- X</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111122</row:id>
|
||||
<row:title>FILE 1 -- Y</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111113</row:id>
|
||||
<row:title>FILE 1 -- Z</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111119</row:id>
|
||||
<row:title>FILE 1 -- AA</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111117</row:id>
|
||||
<row:title>FILE 1 -- BB</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111117</row:id>
|
||||
<row:title>FILE 1 -- CC</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111117</row:id>
|
||||
<row:title>FILE 1 -- DD</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111116</row:id>
|
||||
<row:title>FILE 1 -- EE</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111124</row:id>
|
||||
<row:title>FILE 1 -- FF</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111118</row:id>
|
||||
<row:title>FILE 1 -- GG</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111117</row:id>
|
||||
<row:title>FILE 1 -- HH</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111118</row:id>
|
||||
<row:title>FILE 1 -- II</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111125</row:id>
|
||||
<row:title>FILE 1 -- JJ</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111124</row:id>
|
||||
<row:title>FILE 1 -- KK</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111132</row:id>
|
||||
<row:title>FILE 1 -- LL</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111136</row:id>
|
||||
<row:title>FILE 1 -- MM</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111123</row:id>
|
||||
<row:title>FILE 1 -- NN</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111122</row:id>
|
||||
<row:title>FILE 1 -- OO</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">111110</row:id>
|
||||
<row:title>FILE 1 -- PP</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">1111116</row:id>
|
||||
<row:title>FILE 1 -- QQ</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
</RDF:Bag>
|
||||
</RDF:RDF>
|
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:row="http://dummy/rdf#" xmlns:NC="http://home.netscape.com/NC-rdf#">
|
||||
<RDF:Bag about="urn:data:row">
|
||||
<RDF:li>
|
||||
<RDF:Description>
|
||||
<row:id NC:parseType="Integer">222220</row:id>
|
||||
<row:title>FILE 2 -- A</row:title>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
</RDF:Bag>
|
||||
</RDF:RDF>
|
@ -1,225 +0,0 @@
|
||||
[DEFAULT]
|
||||
skip-if = os == 'android'
|
||||
support-files =
|
||||
animals.rdf
|
||||
animals.sqlite
|
||||
animals.xml
|
||||
bug441785-1.rdf
|
||||
bug441785-2.rdf
|
||||
templates_shared.js
|
||||
|
||||
[test_bug329335.xul]
|
||||
[test_bug330010.xul]
|
||||
skip-if = os == "win"
|
||||
support-files = file_bug330010.rdf
|
||||
[test_bug397148.xul]
|
||||
skip-if = true # Bug 879531
|
||||
[test_bug441785.xul]
|
||||
[test_bug476634.xul]
|
||||
[test_sortservice.xul]
|
||||
[test_tmpl_bindingsextendedsyntax.xul]
|
||||
[test_tmpl_bindingsmultiple.xul]
|
||||
[test_tmpl_bindingsquerysyntax.xul]
|
||||
[test_tmpl_bindingsreversed.xul]
|
||||
[test_tmpl_bindingssameastriple.xul]
|
||||
[test_tmpl_containerandmembervariablechanged.xul]
|
||||
[test_tmpl_containervariablechanged.xul]
|
||||
[test_tmpl_containmentattribute.xul]
|
||||
[test_tmpl_defaultcontainervariableisuri.xul]
|
||||
[test_tmpl_errors.xul]
|
||||
[test_tmpl_extendedsyntax.xul]
|
||||
[test_tmpl_extendedsyntaxemptyconditions.xul]
|
||||
[test_tmpl_extendedsyntaxotherrefvariable.xul]
|
||||
[test_tmpl_extendedsyntaxremoveunmatched.xul]
|
||||
[test_tmpl_extendedsyntaxsimplevariablesubstitution.xul]
|
||||
[test_tmpl_extendedsyntaxtworulesrecurse.xul]
|
||||
[test_tmpl_extendedsyntaxusinganinterveningcontainer.xul]
|
||||
[test_tmpl_extendedvariablesubstitution.xul]
|
||||
[test_tmpl_gridelement.xul]
|
||||
[test_tmpl_htmlelementextendedsyntaxwithbinding.xul]
|
||||
[test_tmpl_htmlelementquerysyntaxrecursive.xul]
|
||||
[test_tmpl_htmlelementquerysyntaxwithmultiplerules.xul]
|
||||
[test_tmpl_htmlelementsimplesyntax.xul]
|
||||
[test_tmpl_htmlelementsimplesyntaxusingatextnode.xul]
|
||||
[test_tmpl_invalidqp.xul]
|
||||
[test_tmpl_listboxelement.xul]
|
||||
[test_tmpl_literalasmember.xul]
|
||||
[test_tmpl_membervariablechanged.xul]
|
||||
[test_tmpl_membervariablesubstitution.xul]
|
||||
[test_tmpl_menuelement.xul]
|
||||
[test_tmpl_menuelementrecursive.xul]
|
||||
[test_tmpl_menulistelement.xul]
|
||||
[test_tmpl_mixedsyntaxiscontainer.xul]
|
||||
[test_tmpl_mixedsyntaxiscontainerisempty.xul]
|
||||
[test_tmpl_mixedsyntaxisempty.xul]
|
||||
[test_tmpl_noaction.xul]
|
||||
[test_tmpl_noactionuriattribute.xul]
|
||||
[test_tmpl_parentconditions.xul]
|
||||
[test_tmpl_parentcontenttag.xul]
|
||||
[test_tmpl_parentsimplesyntax.xul]
|
||||
[test_tmpl_query3triples.xul]
|
||||
[test_tmpl_query3tripleswherecontains.xul]
|
||||
[test_tmpl_querymember3tripleswhereequals.xul]
|
||||
[test_tmpl_querymemberandtwotriples.xul]
|
||||
[test_tmpl_querymembertriplemembertriple.xul]
|
||||
[test_tmpl_queryresourcematch.xul]
|
||||
[test_tmpl_queryreversetriple.xul]
|
||||
[test_tmpl_queryselfwithtriple.xul]
|
||||
[test_tmpl_querysetone.xul]
|
||||
[test_tmpl_querysettwo.xul]
|
||||
[test_tmpl_querysettwowithcondition.xul]
|
||||
[test_tmpl_querysyntax.xul]
|
||||
[test_tmpl_querysyntaxmultiplerules.xul]
|
||||
[test_tmpl_querysyntaxmultiplerulesfirstconditionall.xul]
|
||||
[test_tmpl_querysyntaxmultiplerulestwoconditions.xul]
|
||||
[test_tmpl_querytripleandmembermerge.xul]
|
||||
[test_tmpl_querytripleobjecttosubject.xul]
|
||||
[test_tmpl_querytwomembers.xul]
|
||||
[test_tmpl_querytwomembersfiltered.xul]
|
||||
[test_tmpl_querytwotriples.xul]
|
||||
[test_tmpl_queryupwardsmember.xul]
|
||||
[test_tmpl_queryupwardsmembertripleandfilteringtriple.xul]
|
||||
[test_tmpl_querywithemptyconditions.xul]
|
||||
[test_tmpl_referenceasmember.xul]
|
||||
[test_tmpl_regenerate.xul]
|
||||
[test_tmpl_selfgenerationextendedsyntax.xul]
|
||||
[test_tmpl_selfgenerationsimplesyntax.xul]
|
||||
[test_tmpl_simplesyntaxenclosedinacontainer.xul]
|
||||
[test_tmpl_simplesyntaxenclosedinacontainerwitharule.xul]
|
||||
[test_tmpl_simplesyntaxfilter.xul]
|
||||
[test_tmpl_simplesyntaxfilterwithmultiplerules.xul]
|
||||
[test_tmpl_simplesyntaxfilterwithrule.xul]
|
||||
[test_tmpl_simplesyntaxiteratingoverasinglevalue.xul]
|
||||
[test_tmpl_simplesyntaxusinganinterveningcontainer.xul]
|
||||
[test_tmpl_simplesyntaxusingatextnode.xul]
|
||||
[test_tmpl_simplesyntaxusingcontainerasthegenerationelement.xul]
|
||||
[test_tmpl_simplesyntaxusingdontrecurse.xul]
|
||||
[test_tmpl_simplesyntaxusingrecursivegeneration.xul]
|
||||
[test_tmpl_simplesyntaxusingrecursivegenerationagain.xul]
|
||||
[test_tmpl_simplesyntaxwithtwovariablesused.xul]
|
||||
[test_tmpl_simplevariablesubstitutioncaretsatbeginningandend.xul]
|
||||
[test_tmpl_simplevariablesubstitutioncaretsubstitution.xul]
|
||||
[test_tmpl_simplevariablesubstitutionnovariable.xul]
|
||||
[test_tmpl_simplevariablesubstitutionquestionmarkaspartofvariable.xul]
|
||||
[test_tmpl_simplevariablesubstitutionquestionmarksubstitution.xul]
|
||||
[test_tmpl_simplevariablesubstitutiontextandvariable.xul]
|
||||
[test_tmpl_simplevariablesubstitutionvariableandtextconcatenated.xul]
|
||||
[test_tmpl_simplevariablesubstitutionvariablesconcatenated.xul]
|
||||
[test_tmpl_sortascendinginteger.xul]
|
||||
[test_tmpl_sortascendingquerysyntax.xul]
|
||||
[test_tmpl_sortascendingtworulesquerysyntax.xul]
|
||||
[test_tmpl_sortascendingtworuleswithcontainerquerysyntax.xul]
|
||||
[test_tmpl_sortascendingtworuleswithdifferentcontainerquerysyntax.xul]
|
||||
[test_tmpl_sortdescendingquerysyntax.xul]
|
||||
[test_tmpl_sortquerymemberandtwotriples.xul]
|
||||
[test_tmpl_sortresource2descendingsimplesyntax.xul]
|
||||
[test_tmpl_sortresource2settopredicateascendingquerysyntax.xul]
|
||||
[test_tmpl_sortresource2settopredicatedescendingquerysyntax.xul]
|
||||
[test_tmpl_sortresourceascendingquerysyntax.xul]
|
||||
[test_tmpl_sortresourcedescendingquerysyntax.xul]
|
||||
[test_tmpl_sortresourcesettopredicateascendingquerysyntax.xul]
|
||||
[test_tmpl_sortresourcesettopredicatedescendingquerysyntax.xul]
|
||||
[test_tmpl_sorttworesourcesasstringsettopredicatedescendingquerysyntax.xul]
|
||||
[test_tmpl_sorttworesourcessettopredicateascendingquerysyntax.xul]
|
||||
[test_tmpl_sorttwovariablesascendingquerysyntax.xul]
|
||||
[test_tmpl_sorttwovariablesascendingsimplesyntax.xul]
|
||||
[test_tmpl_sorttwovariablesdescendingquerysyntax.xul]
|
||||
[test_tmpl_sortunknownascendingquerysyntax.xul]
|
||||
[test_tmpl_storage_bad_parameters.xul]
|
||||
[test_tmpl_storage_bad_parameters_2.xul]
|
||||
[test_tmpl_storage_bad_parameters_3.xul]
|
||||
[test_tmpl_storage_baddatasource.xul]
|
||||
[test_tmpl_storage_badquery.xul]
|
||||
[test_tmpl_storage_dynamicparameters.xul]
|
||||
[test_tmpl_storage_listbox.xul]
|
||||
[test_tmpl_storage_multiqueries.xul]
|
||||
[test_tmpl_storage_parameters.xul]
|
||||
[test_tmpl_storage_rule.xul]
|
||||
[test_tmpl_storage_simple.xul]
|
||||
[test_tmpl_storage_sortintegerasc.xul]
|
||||
[test_tmpl_storage_sortintegerdesc.xul]
|
||||
[test_tmpl_storage_sortstringasc.xul]
|
||||
[test_tmpl_storage_sortstringdesc.xul]
|
||||
[test_tmpl_storage_tree.xul]
|
||||
[test_tmpl_treeelementquerysyntax.xul]
|
||||
[test_tmpl_treeelementquerysyntaxnotrecursive.xul]
|
||||
[test_tmpl_treeelementquerysyntaxnotrecursivetreebuilder.xul]
|
||||
[test_tmpl_treeelementquerysyntaxrecursive.xul]
|
||||
[test_tmpl_treeelementquerysyntaxrecursivemultiplerules.xul]
|
||||
[test_tmpl_treeelementquerysyntaxrecursivemultiplerulestreebuilder.xul]
|
||||
[test_tmpl_treeelementquerysyntaxrecursivetreebuilder.xul]
|
||||
[test_tmpl_treeelementquerysyntaxtreebuilder.xul]
|
||||
[test_tmpl_treeelementsimplesyntaxnotrecursive.xul]
|
||||
[test_tmpl_treeelementsimplesyntaxnotrecursivetreebuilder.xul]
|
||||
[test_tmpl_treeelementsimplesyntaxrecursive.xul]
|
||||
[test_tmpl_treeelementsimplesyntaxrecursivetreebuilder.xul]
|
||||
[test_tmpl_treeelementtreecell.xul]
|
||||
[test_tmpl_treeelementtreecellsortascending.xul]
|
||||
[test_tmpl_treeelementtreecellsortascendingtreebuilder.xul]
|
||||
[test_tmpl_treeelementtreecelltreebuilder.xul]
|
||||
[test_tmpl_treeelementtreeitemonly.xul]
|
||||
[test_tmpl_treeelementtreeitemsortascending.xul]
|
||||
[test_tmpl_twogenerationnodes.xul]
|
||||
[test_tmpl_whereafterignorecase.xul]
|
||||
[test_tmpl_whereafterlowercase.xul]
|
||||
[test_tmpl_whereafternegation.xul]
|
||||
[test_tmpl_whereafteruppercase.xul]
|
||||
[test_tmpl_wherebeforeignorecase.xul]
|
||||
[test_tmpl_wherebeforelowercase.xul]
|
||||
[test_tmpl_wherebeforenegation.xul]
|
||||
[test_tmpl_wherebeforeuppercase.xul]
|
||||
[test_tmpl_wherecontains.xul]
|
||||
[test_tmpl_wherecontainsignorecase.xul]
|
||||
[test_tmpl_wherecontainsnegation.xul]
|
||||
[test_tmpl_wherecontainsnumber.xul]
|
||||
[test_tmpl_wherecontainsnumberstring.xul]
|
||||
[test_tmpl_wherecontainsresource.xul]
|
||||
[test_tmpl_wherecontainstwo.xul]
|
||||
[test_tmpl_whereendswith.xul]
|
||||
[test_tmpl_whereendswithignorecase.xul]
|
||||
[test_tmpl_whereendswithnegation.xul]
|
||||
[test_tmpl_whereequals.xul]
|
||||
[test_tmpl_whereequalsignorecase.xul]
|
||||
[test_tmpl_whereequalsmultiple.xul]
|
||||
[test_tmpl_whereequalsmultiplenegation.xul]
|
||||
[test_tmpl_whereequalsmultiplenegationignorecase.xul]
|
||||
[test_tmpl_whereequalsnegation.xul]
|
||||
[test_tmpl_whereequalsnegationignorecase.xul]
|
||||
[test_tmpl_whereequalsnegationwrongcase.xul]
|
||||
[test_tmpl_whereequalsnumber.xul]
|
||||
[test_tmpl_whereequalsothervariable.xul]
|
||||
[test_tmpl_whereequalsresource.xul]
|
||||
[test_tmpl_whereequalssamevariable.xul]
|
||||
[test_tmpl_whereequalswrongcase.xul]
|
||||
[test_tmpl_wheregreater.xul]
|
||||
[test_tmpl_wheregreaternegation.xul]
|
||||
[test_tmpl_wheregreaternegationstring.xul]
|
||||
[test_tmpl_wheregreaterstring.xul]
|
||||
[test_tmpl_whereless.xul]
|
||||
[test_tmpl_wherelessnegation.xul]
|
||||
[test_tmpl_wherelessnegationstring.xul]
|
||||
[test_tmpl_wherelessstring.xul]
|
||||
[test_tmpl_wherenorel.xul]
|
||||
[test_tmpl_wherenosubject.xul]
|
||||
[test_tmpl_wherenovalue.xul]
|
||||
[test_tmpl_wherestartswith.xul]
|
||||
[test_tmpl_wherestartswithignorecase.xul]
|
||||
[test_tmpl_wherestartswithmultiple.xul]
|
||||
[test_tmpl_wherestartswithnegation.xul]
|
||||
[test_tmpl_wherestartswithunknownvariable.xul]
|
||||
[test_tmpl_wherestartswithvariable.xul]
|
||||
[test_tmpl_wheresubjectequalsvariable.xul]
|
||||
[test_tmpl_wheresubjectstartswithvariable.xul]
|
||||
[test_tmpl_xmlquerysimple.xul]
|
||||
[test_tmpl_xmlquerywithassign.xul]
|
||||
[test_tmpl_xmlquerywithassignmentandcondition.xul]
|
||||
[test_tmpl_xmlquerywithassignmentandconditiondontrecurse.xul]
|
||||
[test_tmpl_xmlquerywithbindinginbindings.xul]
|
||||
[test_tmpl_xmlquerywithbindinginrule.xul]
|
||||
[test_tmpl_xmlquerywithdifferentmember.xul]
|
||||
[test_tmpl_xmlquerywithinlinedata.xul]
|
||||
[test_tmpl_xmlquerywithinlinedatawithmultiplequeries.xul]
|
||||
[test_tmpl_xmlquerywithmultiplequeries.xul]
|
||||
[test_tmpl_xmlquerywithothertypes.xul]
|
||||
[test_tmpl_xmlquerywithsort.xul]
|
||||
[test_tmpl_xmlquerywithsortotherfield.xul]
|
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:s="urn:croczilla:xulsvg1:">
|
||||
<rdf:Description about="urn:root">
|
||||
<s:shapes>
|
||||
<rdf:Bag>
|
||||
<rdf:li>
|
||||
<rdf:Description />
|
||||
</rdf:li>
|
||||
</rdf:Bag>
|
||||
</s:shapes>
|
||||
</rdf:Description>
|
||||
</rdf:RDF>
|
@ -1,488 +0,0 @@
|
||||
/**
|
||||
* This script is used for testing XUL templates. Call test_template within
|
||||
* a load event handler.
|
||||
*
|
||||
* A test should have a root node with the datasources attribute with the
|
||||
* id 'root', and a few global variables defined in the test's XUL file:
|
||||
*
|
||||
* testid: the testid, used when outputting test results
|
||||
* expectedOutput: e4x data containing the expected output. It can optionally
|
||||
* be enclosed in an <output> element as most tests generate
|
||||
* more than one node of output.
|
||||
* isTreeBuilder: true for dont-build-content trees, false otherwise
|
||||
* queryType: 'rdf', 'xml', etc.
|
||||
* needsOpen: true for menu tests where the root menu must be opened before
|
||||
* comparing results
|
||||
* notWorkingYet: true if this test isn't working yet, outputs todo results
|
||||
* notWorkingYetDynamic: true if the dynamic changes portion of the test
|
||||
* isn't working yet, outputs todo results
|
||||
* changes: an array of functions to perform in sequence to test dynamic changes
|
||||
* to the datasource.
|
||||
*
|
||||
* If the <output> element has an unordered attribute set to true, the
|
||||
* children within it must all appear to match, but may appear in any order.
|
||||
* If the unordered attribute is not set, the children must appear in the same
|
||||
* order.
|
||||
*
|
||||
* If the 'changes' array is used, it should be an array of functions. Each
|
||||
* function will be called in order and a comparison of the output will be
|
||||
* performed. This allows changes to be made to the datasource to ensure that
|
||||
* the generated template output has been updated. Within the expected output
|
||||
* XML, the step attribute may be set to a number on an element to indicate
|
||||
* that an element only applies before or after a particular change. If step
|
||||
* is set to a positive number, that element will only exist after that step in
|
||||
* the list of changes made. If step is set to a negative number, that element
|
||||
* will only exist until that step. Steps are numbered starting at 1. For
|
||||
* example:
|
||||
* <label value="Cat"/>
|
||||
* <label step="2" value="Dog"/>
|
||||
* <label step="-5" value="Mouse"/>
|
||||
* The first element will always exist. The second element will only appear
|
||||
* after the second change is made. The third element will only appear until
|
||||
* the fifth change and it will no longer be present at later steps.
|
||||
*
|
||||
* If the anyid attribute is set to true on an element in the expected output,
|
||||
* then the value of the id attribute on that element is not compared for a
|
||||
* match. This is used, for example, for xml datasources, where the ids set on
|
||||
* the generated output are pseudo-random.
|
||||
*/
|
||||
|
||||
const ZOO_NS = "http://www.some-fictitious-zoo.com/";
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const debug = false;
|
||||
|
||||
var expectedConsoleMessages = [];
|
||||
var expectLoggedMessages = null;
|
||||
|
||||
function get_RDF() {
|
||||
try {
|
||||
return Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Components.interfaces.nsIRDFService);
|
||||
} catch (ex) { }
|
||||
}
|
||||
|
||||
function get_ContainerUtils()
|
||||
{
|
||||
try {
|
||||
return Components.classes["@mozilla.org/rdf/container-utils;1"].
|
||||
getService(Components.interfaces.nsIRDFContainerUtils);
|
||||
} catch(ex) { }
|
||||
}
|
||||
|
||||
const RDF = get_RDF();
|
||||
const ContainerUtils = get_ContainerUtils();
|
||||
|
||||
var xmlDoc;
|
||||
|
||||
function test_template()
|
||||
{
|
||||
var root = document.getElementById("root");
|
||||
|
||||
var ds;
|
||||
if (queryType == "rdf" && RDF) {
|
||||
var ioService = Components.classes["@mozilla.org/network/io-service;1"].
|
||||
getService(Components.interfaces.nsIIOService);
|
||||
|
||||
var src = window.location.href.replace(/test_tmpl.*xul/, "animals.rdf");
|
||||
ds = RDF.GetDataSourceBlocking(src);
|
||||
|
||||
if (expectLoggedMessages) {
|
||||
Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService).reset();
|
||||
}
|
||||
|
||||
if (root.getAttribute("datasources") == "rdf:null")
|
||||
root.setAttribute("datasources", "animals.rdf");
|
||||
}
|
||||
else if (queryType == "xml") {
|
||||
var src = window.location.href.replace(/test_tmpl.*xul/, "animals.xml");
|
||||
xmlDoc = new XMLHttpRequest();
|
||||
xmlDoc.open("get", src, false);
|
||||
xmlDoc.send(null);
|
||||
}
|
||||
|
||||
// open menus if necessary
|
||||
if (needsOpen)
|
||||
root.open = true;
|
||||
|
||||
if (expectLoggedMessages)
|
||||
expectLoggedMessages();
|
||||
|
||||
checkResults(root, 0);
|
||||
|
||||
if (changes.length) {
|
||||
var usedds = ds;
|
||||
// within these chrome tests, RDF datasources won't be modifiable unless
|
||||
// an in-memory datasource is used instead. Call copyRDFDataSource to
|
||||
// copy the datasource.
|
||||
if (queryType == "rdf")
|
||||
usedds = copyRDFDataSource(root, ds);
|
||||
if (needsOpen)
|
||||
root.open = true;
|
||||
setTimeout(iterateChanged, 0, root, usedds);
|
||||
}
|
||||
else {
|
||||
if (needsOpen)
|
||||
root.open = false;
|
||||
if (expectedConsoleMessages.length)
|
||||
compareConsoleMessages();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function iterateChanged(root, ds)
|
||||
{
|
||||
Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService).reset();
|
||||
|
||||
for (var c = 0; c < changes.length; c++) {
|
||||
changes[c](ds, root);
|
||||
checkResults(root, c + 1);
|
||||
}
|
||||
|
||||
if (needsOpen)
|
||||
root.open = false;
|
||||
if (expectedConsoleMessages.length)
|
||||
compareConsoleMessages();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function checkResults(root, step)
|
||||
{
|
||||
var output = expectedOutput.cloneNode(true);
|
||||
setForCurrentStep(output, step);
|
||||
|
||||
var error;
|
||||
var actualoutput = root;
|
||||
if (isTreeBuilder) {
|
||||
// convert the tree's view data into the equivalent DOM structure
|
||||
// for easier comparison
|
||||
actualoutput = treeViewToDOM(root);
|
||||
var treechildrenElements = [...output.children].filter((e) => e.localName === "treechildren");
|
||||
error = compareOutput(actualoutput, treechildrenElements[0], false);
|
||||
}
|
||||
else {
|
||||
error = compareOutput(actualoutput, output, true);
|
||||
}
|
||||
|
||||
var adjtestid = testid;
|
||||
if (step > 0)
|
||||
adjtestid += " dynamic step " + step;
|
||||
|
||||
var stilltodo = ((step == 0 && notWorkingYet) || (step > 0 && notWorkingYetDynamic));
|
||||
if (stilltodo)
|
||||
todo(false, adjtestid);
|
||||
else
|
||||
ok(!error, adjtestid);
|
||||
|
||||
if ((!stilltodo && error) || debug) {
|
||||
// for debugging, serialize the XML output
|
||||
var serializedXML = "";
|
||||
var rootNodes = actualoutput.childNodes;
|
||||
for (var n = 0; n < rootNodes.length; n++) {
|
||||
var node = rootNodes[n];
|
||||
if (node.localName != "template")
|
||||
serializedXML += ((new XMLSerializer()).serializeToString(node));
|
||||
}
|
||||
|
||||
// remove the XUL namespace declarations to make the output more readable
|
||||
const nsrepl = new RegExp("xmlns=\"" + XUL_NS + "\" ", "g");
|
||||
serializedXML = serializedXML.replace(nsrepl, "");
|
||||
if (debug)
|
||||
dump("-------- " + adjtestid + " " + error + ":\n" + serializedXML + "\n");
|
||||
if (!stilltodo && error)
|
||||
is(serializedXML, "Same", "Error is: " + error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the expected output to acccount for any step attributes.
|
||||
*/
|
||||
function setForCurrentStep(content, currentStep)
|
||||
{
|
||||
var todelete = [];
|
||||
for (var child of content.childNodes) {
|
||||
if (child.nodeType === Node.ELEMENT_NODE) {
|
||||
var stepstr = child.getAttribute("step") || "";
|
||||
var stepsarr = stepstr.split(",");
|
||||
for (var s = 0; s < stepsarr.length; s++) {
|
||||
var step = parseInt(stepsarr[s]);
|
||||
if ((step > 0 && step > currentStep) ||
|
||||
(step < 0 && -step <= currentStep)) {
|
||||
todelete.push(child);
|
||||
}
|
||||
}
|
||||
} else if (child.nodeType === Node.TEXT_NODE) {
|
||||
// Drop empty text nodes.
|
||||
if (child.nodeValue.trim() === "")
|
||||
todelete.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
for (var e of todelete)
|
||||
content.removeChild(e);
|
||||
|
||||
for (var child of content.children) {
|
||||
child.removeAttribute("step");
|
||||
setForCurrentStep(child, currentStep);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the 'actual' DOM output with the 'expected' output. This function
|
||||
* is called recursively, with isroot true if actual refers to the root of the
|
||||
* template. Returns a null string if they are equal and an error string if
|
||||
* they are not equal. This function is called recursively as it iterates
|
||||
* through each node in the DOM tree.
|
||||
*/
|
||||
function compareOutput(actual, expected, isroot)
|
||||
{
|
||||
if (isroot && expected.localName != "data")
|
||||
return "expected must be a <data> element";
|
||||
|
||||
var t;
|
||||
|
||||
// compare text nodes
|
||||
if (expected.nodeType == Node.TEXT_NODE) {
|
||||
if (actual.nodeValue !== expected.nodeValue.trim())
|
||||
return "Text " + actual.nodeValue + " doesn't match " + expected.nodeValue;
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!isroot) {
|
||||
var anyid = false;
|
||||
// make sure that the tags match
|
||||
if (actual.localName != expected.localName)
|
||||
return "Tag name " + expected.localName + " not found";
|
||||
|
||||
// loop through the attributes in the expected node and compare their
|
||||
// values with the corresponding attribute on the actual node
|
||||
|
||||
var expectedAttrs = expected.attributes;
|
||||
for (var a = 0; a < expectedAttrs.length; a++) {
|
||||
var attr = expectedAttrs[a];
|
||||
var expectval = attr.value;
|
||||
// skip checking the id when anyid="true", however make sure to
|
||||
// ensure that the id is actually present.
|
||||
if (attr.name == "anyid" && expectval == "true") {
|
||||
anyid = true;
|
||||
if (!actual.hasAttribute("id"))
|
||||
return "expected id attribute";
|
||||
}
|
||||
else if (actual.getAttribute(attr.name) != expectval) {
|
||||
return "attribute " + attr.name + " is '" +
|
||||
actual.getAttribute(attr.name) + "' instead of '" + expectval + "'";
|
||||
}
|
||||
}
|
||||
|
||||
// now loop through the actual attributes and make sure that there aren't
|
||||
// any extra attributes that weren't expected
|
||||
var length = actual.attributes.length;
|
||||
for (t = 0; t < length; t++) {
|
||||
var aattr = actual.attributes[t];
|
||||
var expectval = expected.getAttribute(aattr.name);
|
||||
// ignore some attributes that don't matter
|
||||
if (expectval != actual.getAttribute(aattr.name) &&
|
||||
aattr.name != "staticHint" && aattr.name != "xmlns" &&
|
||||
(aattr.name != "id" || !anyid))
|
||||
return "extra attribute " + aattr.name;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the node has the right number of children. Subtract one for
|
||||
// the root node to account for the <template> node.
|
||||
length = actual.childNodes.length - (isroot ? 1 : 0);
|
||||
if (length != expected.childNodes.length)
|
||||
return "incorrect child node count of " + actual.localName + " " + length +
|
||||
" expected " + expected.childNodes.length;
|
||||
|
||||
// if <data unordered="true"> is used, then the child nodes may be in any order
|
||||
var unordered = (expected.localName == "data" && expected.getAttribute("unordered") == "true");
|
||||
|
||||
// next, loop over the children and call compareOutput recursively on each one
|
||||
var adj = 0;
|
||||
for (t = 0; t < actual.childNodes.length; t++) {
|
||||
var actualnode = actual.childNodes[t];
|
||||
// skip the <template> element, and add one to the indices when looking
|
||||
// at the later nodes to account for it
|
||||
if (isroot && actualnode.localName == "template") {
|
||||
adj++;
|
||||
}
|
||||
else {
|
||||
var output = "unexpected";
|
||||
if (unordered) {
|
||||
var expectedChildren = expected.childNodes;
|
||||
for (var e = 0; e < expectedChildren.length; e++) {
|
||||
output = compareOutput(actualnode, expectedChildren[e], false);
|
||||
if (!output)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
output = compareOutput(actualnode, expected.childNodes[t - adj], false);
|
||||
}
|
||||
|
||||
// an error was returned, so return early
|
||||
if (output)
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* copy the datasource into an in-memory datasource so that it can be modified
|
||||
*/
|
||||
function copyRDFDataSource(root, sourceds)
|
||||
{
|
||||
var dsourcesArr = [];
|
||||
var composite = root.database;
|
||||
var dsources = composite.GetDataSources();
|
||||
while (dsources.hasMoreElements()) {
|
||||
sourceds = dsources.getNext().QueryInterface(Components.interfaces.nsIRDFDataSource);
|
||||
dsourcesArr.push(sourceds);
|
||||
}
|
||||
|
||||
for (var d = 0; d < dsourcesArr.length; d++)
|
||||
composite.RemoveDataSource(dsourcesArr[d]);
|
||||
|
||||
var newds = Components.classes["@mozilla.org/rdf/datasource;1?name=in-memory-datasource"].
|
||||
createInstance(Components.interfaces.nsIRDFDataSource);
|
||||
|
||||
var sourcelist = sourceds.GetAllResources();
|
||||
while (sourcelist.hasMoreElements()) {
|
||||
var source = sourcelist.getNext();
|
||||
var props = sourceds.ArcLabelsOut(source);
|
||||
while (props.hasMoreElements()) {
|
||||
var prop = props.getNext();
|
||||
if (prop instanceof Components.interfaces.nsIRDFResource) {
|
||||
var targets = sourceds.GetTargets(source, prop, true);
|
||||
while (targets.hasMoreElements())
|
||||
newds.Assert(source, prop, targets.getNext(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
composite.AddDataSource(newds);
|
||||
root.builder.rebuild();
|
||||
|
||||
return newds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a tree view (nsITreeView) into the equivalent DOM tree.
|
||||
* Returns the treechildren
|
||||
*/
|
||||
function treeViewToDOM(tree)
|
||||
{
|
||||
var treechildren = document.createElement("treechildren");
|
||||
|
||||
if (tree.view)
|
||||
treeViewToDOMInner(tree.columns, treechildren, tree.view, tree.builder, 0, 0);
|
||||
|
||||
return treechildren;
|
||||
}
|
||||
|
||||
function treeViewToDOMInner(columns, treechildren, view, builder, start, level)
|
||||
{
|
||||
var end = view.rowCount;
|
||||
|
||||
for (var i = start; i < end; i++) {
|
||||
if (view.getLevel(i) < level)
|
||||
return i - 1;
|
||||
|
||||
var id = builder ? builder.getResourceAtIndex(i).Value : "id" + i;
|
||||
var item = document.createElement("treeitem");
|
||||
item.setAttribute("id", id);
|
||||
treechildren.appendChild(item);
|
||||
|
||||
var row = document.createElement("treerow");
|
||||
item.appendChild(row);
|
||||
|
||||
for (var c = 0; c < columns.length; c++) {
|
||||
var cell = document.createElement("treecell");
|
||||
var label = view.getCellText(i, columns[c]);
|
||||
if (label)
|
||||
cell.setAttribute("label", label);
|
||||
row.appendChild(cell);
|
||||
}
|
||||
|
||||
if (view.isContainer(i)) {
|
||||
item.setAttribute("container", "true");
|
||||
item.setAttribute("empty", view.isContainerEmpty(i) ? "true" : "false");
|
||||
|
||||
if (!view.isContainerEmpty(i) && view.isContainerOpen(i)) {
|
||||
item.setAttribute("open", "true");
|
||||
|
||||
var innertreechildren = document.createElement("treechildren");
|
||||
item.appendChild(innertreechildren);
|
||||
|
||||
i = treeViewToDOMInner(columns, innertreechildren, view, builder, i + 1, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
function expectConsoleMessage(ref, id, isNew, isActive, extra)
|
||||
{
|
||||
var message = "In template with id root" +
|
||||
(ref ? " using ref " + ref : "") + "\n " +
|
||||
(isNew ? "New " : "Removed ") + (isActive ? "active" : "inactive") +
|
||||
" result for query " + extra + ": " + id;
|
||||
expectedConsoleMessages.push(message);
|
||||
}
|
||||
|
||||
function compareConsoleMessages()
|
||||
{
|
||||
var consoleService = Components.classes["@mozilla.org/consoleservice;1"].
|
||||
getService(Components.interfaces.nsIConsoleService);
|
||||
var messages = consoleService.getMessageArray() || [];
|
||||
messages = messages.map(m => m.message);
|
||||
// Copy to avoid modifying expectedConsoleMessages
|
||||
var expect = expectedConsoleMessages.concat();
|
||||
for (var m = 0; m < messages.length; m++) {
|
||||
if (messages[m] == expect[0]) {
|
||||
ok(true, "found message " + expect.shift());
|
||||
}
|
||||
}
|
||||
if (expect.length != 0) {
|
||||
ok(false, "failed to find expected console messages: " + expect);
|
||||
}
|
||||
}
|
||||
|
||||
function copyToProfile(filename)
|
||||
{
|
||||
if (Cc === undefined) {
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
}
|
||||
|
||||
var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]
|
||||
.getService(Ci.mozIJSSubScriptLoader);
|
||||
loader.loadSubScript("chrome://mochikit/content/chrome-harness.js");
|
||||
|
||||
var file = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties)
|
||||
.get("ProfD", Ci.nsIFile);
|
||||
file.append(filename);
|
||||
|
||||
var parentURI = getResolvedURI(getRootDirectory(window.location.href));
|
||||
if (parentURI.JARFile) {
|
||||
parentURI = extractJarToTmp(parentURI);
|
||||
} else {
|
||||
var fileHandler = Cc["@mozilla.org/network/protocol;1?name=file"].
|
||||
getService(Ci.nsIFileProtocolHandler);
|
||||
parentURI = fileHandler.getFileFromURLSpec(parentURI.spec);
|
||||
}
|
||||
|
||||
parentURI = parentURI.QueryInterface(Ci.nsIFile);
|
||||
parentURI.append(filename);
|
||||
try {
|
||||
var retVal = parentURI.copyToFollowingLinks(file.parent, filename);
|
||||
} catch (ex) {
|
||||
//ignore this error as the file could exist already
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function init()
|
||||
{
|
||||
document.documentElement.appendChild(document.getElementById("svg"));
|
||||
ok(true, "Didn't crash");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", init, false);
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<svg:svg datasources="" id="svg"/>
|
||||
|
||||
|
||||
</window>
|
@ -1,51 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
onload="boom();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
<script type="text/javascript">
|
||||
<![CDATA[
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
function boom()
|
||||
{
|
||||
const RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Components.interfaces.nsIRDFService);
|
||||
var src = window.location.href.replace(/test_bug330010.xul/, "file_bug330010.rdf");
|
||||
|
||||
var ds = RDF.GetDataSourceBlocking(src);
|
||||
|
||||
var s = document.getElementById("s");
|
||||
s.setAttribute("datasources", "file_bug330010.rdf");
|
||||
|
||||
var x = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "hbox");
|
||||
var generatedShape = s.childNodes[3];
|
||||
generatedShape.appendChild(x);
|
||||
document.documentElement.removeChild(document.getElementById("s"));
|
||||
ok(true, "Didn't crash");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<html:div datasources="rdf:null" ref="urn:root" flex="1" id="s">
|
||||
<template>
|
||||
<rule>
|
||||
<conditions>
|
||||
<content uri="?root"/>
|
||||
<triple subject="?root"
|
||||
predicate="urn:croczilla:xulsvg1:shapes"
|
||||
object="?shapes"/>
|
||||
<member container="?shapes" child="?shape" id="m"/>
|
||||
</conditions>
|
||||
<action>
|
||||
<hbox id="p" uri="?shape" />
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
</html:div>
|
||||
</window>
|
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" xmlns:html="http://www.w3.org/1999/xhtml" onload="boom();">
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
||||
|
||||
<script type="text/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function boom() {
|
||||
ok(true, "Didn't crash");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<html:span datasources="0" />
|
||||
|
||||
</window>
|
@ -1,148 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<tree flex="20" id="t" ref="urn:data:row" datasources="rdf:null" seltype="single">
|
||||
<treecols>
|
||||
<treecol flex="1" id="id" label="id" sort="rdf:http://dummy/rdf#id" />
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol flex="1" id="title" label="title" sort="rdf:http://dummy/rdf#title" sortActive="true" sortDirection="ascending" /><splitter class="tree-splitter"/>
|
||||
</treecols>
|
||||
<template>
|
||||
<treechildren>
|
||||
<treeitem uri="rdf:*" seltype="single">
|
||||
<treerow >
|
||||
<treecell label="rdf:http://dummy/rdf#id"/>
|
||||
<treecell label="rdf:http://dummy/rdf#title"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</template>
|
||||
</tree>
|
||||
<tree flex="20" id="tc" ref="urn:data:row" datasources="rdf:null" seltype="single" flags="dont-build-content">
|
||||
<treecols>
|
||||
<treecol flex="1" id="idc" label="id" sort="rdf:http://dummy/rdf#id" />
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol flex="1" id="titlec" label="title" sort="rdf:http://dummy/rdf#title" sortActive="true" sortDirection="ascending" /><splitter class="tree-splitter"/>
|
||||
</treecols>
|
||||
<template>
|
||||
<treechildren>
|
||||
<treeitem uri="rdf:*" seltype="single">
|
||||
<treerow >
|
||||
<treecell label="rdf:http://dummy/rdf#id"/>
|
||||
<treecell label="rdf:http://dummy/rdf#title"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
</template>
|
||||
</tree>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/x-javascript">
|
||||
<![CDATA[
|
||||
|
||||
var buildCount = 0;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var TemplateBuilderListener = {
|
||||
willRebuild: function(aBuilder) {
|
||||
},
|
||||
|
||||
didRebuild: function(aBuilder) {
|
||||
++buildCount;
|
||||
var remove = false;
|
||||
if (buildCount == 2) {
|
||||
remove =true;
|
||||
setTimeout(nextDataSource, 0);
|
||||
} else if (buildCount == 4) {
|
||||
remove = true;
|
||||
setTimeout(continueTest, 0);
|
||||
}
|
||||
if (remove) {
|
||||
var tree = document.getElementById('t');
|
||||
var treec = document.getElementById('tc');
|
||||
tree.builder.removeListener(TemplateBuilderListener);
|
||||
treec.builder.removeListener(TemplateBuilderListener);
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: function (aIID)
|
||||
{
|
||||
if (!aIID.equals(Components.interfaces.nsIXULBuilderListener) &&
|
||||
!aIID.equals(Components.interfaces.nsISupports))
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
function runTest() {
|
||||
var tree = document.getElementById('t');
|
||||
var treec = document.getElementById('tc');
|
||||
|
||||
try {
|
||||
var rdfService = Components.classes["@mozilla.org/rdf/rdf-service;1"].
|
||||
getService(Components.interfaces.nsIRDFService);
|
||||
|
||||
var s1 = window.location.href.replace(/test_bug441785.xul/, "bug441785-1.rdf");
|
||||
var ds1 = rdfService.GetDataSourceBlocking(s1);
|
||||
|
||||
var s2 = window.location.href.replace(/test_bug441785.xul/, "bug441785-2.rdf");
|
||||
var ds2 = rdfService.GetDataSourceBlocking(s2);
|
||||
} catch (ex) { }
|
||||
|
||||
tree.builder.addListener(TemplateBuilderListener);
|
||||
treec.builder.addListener(TemplateBuilderListener);
|
||||
tree.setAttribute('datasources', 'bug441785-1.rdf');
|
||||
treec.setAttribute('datasources', 'bug441785-1.rdf');
|
||||
}
|
||||
|
||||
var oldtreefirstrow, oldtreecfirstrow;
|
||||
|
||||
function nextDataSource()
|
||||
{
|
||||
var tree = document.getElementById('t');
|
||||
var treec = document.getElementById('tc');
|
||||
tree.treeBoxObject.scrollToRow(10);
|
||||
treec.treeBoxObject.scrollToRow(10);
|
||||
|
||||
is(tree.treeBoxObject.getFirstVisibleRow(), 10, "first tree row count datasource 1");
|
||||
is(treec.treeBoxObject.getFirstVisibleRow(), 10, "second tree row count datasource 1");
|
||||
|
||||
tree.builder.addListener(TemplateBuilderListener);
|
||||
treec.builder.addListener(TemplateBuilderListener);
|
||||
tree.setAttribute('datasources', 'bug441785-2.rdf');
|
||||
treec.setAttribute('datasources', 'bug441785-2.rdf');
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
var tree = document.getElementById('t');
|
||||
var treec = document.getElementById('tc');
|
||||
|
||||
is(tree.treeBoxObject.getFirstVisibleRow(), 0, "first tree row count datasource 2");
|
||||
is(treec.treeBoxObject.getFirstVisibleRow(), 0, "second tree row count datasource 2");
|
||||
|
||||
try {
|
||||
window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils)
|
||||
.garbageCollect();
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
// Hit the bug, crash
|
||||
// (not exactly the same kind of crash as 441785, but from the same cause)
|
||||
tree.remove();
|
||||
treec.remove();
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", runTest, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -1,76 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=476634
|
||||
-->
|
||||
<window title="Mozilla Bug 476634" onload="startup()"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=304188">Mozilla Bug 476634</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
<template id="test-template">
|
||||
<query>SELECT id,value FROM test</query>
|
||||
<action>
|
||||
<label uri="?" id="?id" value="?value"/>
|
||||
</action>
|
||||
</template>
|
||||
<vbox id="results-list" datasources="rdf:null" querytype="storage" ref="*"
|
||||
template="test-template"/>
|
||||
|
||||
<script class="testbody" type="application/javascript">
|
||||
<![CDATA[
|
||||
function startup() {
|
||||
var ss = Components.classes["@mozilla.org/storage/service;1"]
|
||||
.getService(Components.interfaces.mozIStorageService);
|
||||
var db = ss.openSpecialDatabase("memory");
|
||||
|
||||
db.createTable("test", "id TEXT, value INTEGER");
|
||||
var stmt = db.createStatement("INSERT INTO test (id, value) VALUES (?,?)");
|
||||
stmt.bindByIndex(0, "test1");
|
||||
stmt.bindByIndex(1, 0);
|
||||
stmt.execute();
|
||||
stmt.bindByIndex(0, "test2");
|
||||
stmt.bindByIndex(1, 2147483647);
|
||||
stmt.execute();
|
||||
stmt.bindByIndex(0, "test3");
|
||||
stmt.bindByIndex(1, -2147483648);
|
||||
stmt.execute();
|
||||
stmt.bindByIndex(0, "test4");
|
||||
stmt.bindByIndex(1, 0);
|
||||
stmt.execute();
|
||||
stmt.bindByIndex(0, "test5");
|
||||
stmt.bindByIndex(1, 3147483647);
|
||||
stmt.execute();
|
||||
stmt.bindByIndex(0, "test6");
|
||||
stmt.bindByIndex(1, -3147483648);
|
||||
stmt.execute();
|
||||
stmt.finalize();
|
||||
|
||||
var list = document.getElementById("results-list");
|
||||
list.builder.datasource = db;
|
||||
|
||||
is(list.childNodes.length, 6, "Should be 6 generated elements");
|
||||
is(list.childNodes[0].value, "0", "Should have seen the correct value");
|
||||
is(list.childNodes[1].value, "2147483647", "Should have seen the correct value");
|
||||
is(list.childNodes[2].value, "-2147483648", "Should have seen the correct value");
|
||||
is(list.childNodes[3].value, "0", "Should have seen the correct value");
|
||||
is(list.childNodes[4].value, "3147483647", "Should have seen the correct value");
|
||||
is(list.childNodes[5].value, "-3147483648", "Should have seen the correct value");
|
||||
}
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</window>
|
@ -1,70 +0,0 @@
|
||||
<?xml version="1.0" ?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
|
||||
<vbox id="box"/>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/x-javascript">
|
||||
<![CDATA[
|
||||
|
||||
var tests = [
|
||||
[["One", "Two", "Three", "Four"], "", "Four One Three Two"],
|
||||
[["One", "Two", "Three", "Four"], "integer", "Four One Three Two"],
|
||||
[["One", "Two", "Three", "Four"], "descending", "Two Three One Four"],
|
||||
[["One", "Two", "Three", "Four"], "descending integer", "Two Three One Four"],
|
||||
[["One", "Two", "Three", "Four"], "integer cat descending", "Two Three One Four"],
|
||||
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "", "1 12 13 170 2 2 222 240 7 98"],
|
||||
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "integer", "1 2 2 7 12 13 98 170 222 240"],
|
||||
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "ascending integer", "1 2 2 7 12 13 98 170 222 240"],
|
||||
[["1", "13", "2", "7", "12", "240", "2", "170", "222", "98"], "integer descending", "240 222 170 98 13 12 7 2 2 1"],
|
||||
[["Cat", "cat", "Candy", "candy"], "comparecase", "Candy Cat candy cat"],
|
||||
[["1", "102", "22", "One", "40", "Two"], "integer", "1 22 40 102 One Two"],
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
function doTests()
|
||||
{
|
||||
var box = document.getElementById("box");
|
||||
|
||||
const sortService = Components.classes["@mozilla.org/xul/xul-sort-service;1"].
|
||||
getService(Components.interfaces.nsIXULSortService);
|
||||
|
||||
for (let t = 0; t < tests.length; t++) {
|
||||
var test = tests[t];
|
||||
|
||||
for (let e = 0; e < test[0].length; e++) {
|
||||
var label = document.createElement("label");
|
||||
label.setAttribute("value", test[0][e]);
|
||||
box.appendChild(label);
|
||||
}
|
||||
|
||||
sortService.sort(box, "value", test[1]);
|
||||
|
||||
var actual = "";
|
||||
for (let e = 0; e < box.childNodes.length; e++) {
|
||||
if (actual)
|
||||
actual += " ";
|
||||
actual += box.childNodes[e].getAttribute("value");
|
||||
}
|
||||
is(actual, test[2], "sorted step " + (t + 1));
|
||||
|
||||
while(box.hasChildNodes())
|
||||
box.firstChild.remove();
|
||||
box.removeAttribute("sortDirection");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", doTests, false);
|
||||
|
||||
]]>
|
||||
</script>
|
||||
</window>
|
@ -1,73 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
|
||||
<!--
|
||||
bindings - extended syntax
|
||||
-->
|
||||
|
||||
<window title="XUL Template Tests" width="500" height="600"
|
||||
onload="test_template();"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||
|
||||
<data id="output">
|
||||
<label step="-2" id="http://www.some-fictitious-zoo.com/humans/sarah" value="Sarah "/>
|
||||
<label step="2" id="http://www.some-fictitious-zoo.com/humans/sarah" value="Sarah Yarmouth"/>
|
||||
<label step="-1" id="http://www.some-fictitious-zoo.com/humans/robert" value="Robert Sanderson"/>
|
||||
<label step="1" id="http://www.some-fictitious-zoo.com/humans/robert" value="Robert "/>
|
||||
</data>
|
||||
|
||||
<script src="templates_shared.js"/>
|
||||
|
||||
<script>
|
||||
<![CDATA[
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var testid ="bindings - extended syntax";
|
||||
var queryType = "rdf";
|
||||
var isTreeBuilder = false;
|
||||
var needsOpen = false;
|
||||
var notWorkingYet = false;
|
||||
var notWorkingYetDynamic = false;
|
||||
var expectedOutput = document.getElementById("output");
|
||||
|
||||
var changes = [
|
||||
// step 1
|
||||
function(targetds, root) {
|
||||
targetds.Unassert(RDF.GetResource(ZOO_NS + 'humans/robert'),
|
||||
RDF.GetResource(ZOO_NS + 'rdf#lastName'),
|
||||
RDF.GetLiteral('Sanderson'), true);
|
||||
},
|
||||
// step 2
|
||||
function(targetds, root) {
|
||||
targetds.Assert(RDF.GetResource(ZOO_NS + 'humans/sarah'),
|
||||
RDF.GetResource(ZOO_NS + 'rdf#lastName'),
|
||||
RDF.GetLiteral('Yarmouth'), true);
|
||||
}
|
||||
];
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="root" datasources="rdf:null" ref="http://www.some-fictitious-zoo.com/humans">
|
||||
<template id="template">
|
||||
<rule>
|
||||
<conditions>
|
||||
<content uri="?uri"/>
|
||||
<member container="?uri" child="?child"/>
|
||||
<triple subject="?child" predicate="http://www.some-fictitious-zoo.com/rdf#name" object="?name"/>
|
||||
</conditions>
|
||||
<bindings>
|
||||
<binding subject="?child" predicate="http://www.some-fictitious-zoo.com/rdf#lastName" object="?lastname"/>
|
||||
</bindings>
|
||||
<action>
|
||||
<label uri="?child" value="?name ?lastname"/>
|
||||
</action>
|
||||
</rule>
|
||||
</template>
|
||||
</vbox>
|
||||
|
||||
</window>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user