зеркало из https://github.com/mozilla/gecko-dev.git
473 строки
15 KiB
C++
473 строки
15 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
* http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
* for the specific language governing rights and limitations under the
|
|
* License.
|
|
*
|
|
* The Original Code is Mozilla XForms support.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Novell, Inc.
|
|
* Portions created by the Initial Developer are Copyright (C) 2004
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Allan Beaufour <abeaufour@novell.com>
|
|
* David Landwehr <dlandwehr@novell.com>
|
|
*
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
* the provisions above, a recipient may use your version of this file under
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#ifndef __NSXFORMSMDGENGINE__
|
|
#define __NSXFORMSMDGENGINE__
|
|
|
|
#include "nscore.h"
|
|
#include "nsClassHashtable.h"
|
|
#include "nsCOMPtr.h"
|
|
#include "nsDataHashtable.h"
|
|
#include "nsVoidArray.h"
|
|
|
|
#include "nsIDOMNode.h"
|
|
|
|
#include "nsXFormsTypes.h"
|
|
#include "nsXFormsMDGSet.h"
|
|
|
|
class nsIDOMXPathExpression;
|
|
|
|
/**
|
|
* Flags, etc.
|
|
*
|
|
* TODO: Convert to enum?
|
|
*/
|
|
const PRUint16 MDG_FLAG_READONLY = 1 << 1;
|
|
const PRUint16 MDG_FLAG_CONSTRAINT = 1 << 2;
|
|
const PRUint16 MDG_FLAG_RELEVANT = 1 << 3;
|
|
const PRUint16 MDG_FLAG_REQUIRED = 1 << 4;
|
|
const PRUint16 MDG_FLAG_SCHEMA_VALID = 1 << 5;
|
|
const PRUint16 MDG_FLAG_VALID = 1 << 6;
|
|
const PRUint16 MDG_FLAG_INHERITED_RELEVANT = 1 << 7;
|
|
const PRUint16 MDG_FLAG_INHERITED_READONLY = 1 << 8;
|
|
const PRUint16 MDG_FLAG_DISPATCH_VALUE_CHANGED = 1 << 9;
|
|
const PRUint16 MDG_FLAG_DISPATCH_READONLY_CHANGED = 1 << 10;
|
|
const PRUint16 MDG_FLAG_DISPATCH_VALID_CHANGED = 1 << 11;
|
|
const PRUint16 MDG_FLAG_DISPATCH_RELEVANT_CHANGED = 1 << 12;
|
|
const PRUint16 MDG_FLAG_DISPATCH_REQUIRED_CHANGED = 1 << 13;
|
|
const PRUint16 MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED = 1 << 14;
|
|
|
|
const PRUint16 MDG_FLAGMASK_NOT_DISPATCH = ~(MDG_FLAG_DISPATCH_VALUE_CHANGED | \
|
|
MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
|
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
|
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
|
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
|
|
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED);
|
|
|
|
const PRUint16 MDG_FLAG_DEFAULT = MDG_FLAG_CONSTRAINT | \
|
|
MDG_FLAG_RELEVANT |\
|
|
MDG_FLAG_INHERITED_RELEVANT;
|
|
|
|
const PRUint16 MDG_FLAG_INITIAL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
|
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
|
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
|
MDG_FLAG_DISPATCH_REQUIRED_CHANGED;
|
|
|
|
const PRUint16 MDG_FLAG_ALL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
|
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
|
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
|
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
|
|
MDG_FLAG_DISPATCH_VALUE_CHANGED |\
|
|
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED;
|
|
|
|
|
|
|
|
/**
|
|
* Data structure for nodes in the graph.
|
|
*
|
|
* There is one node per type (calculate, readonly, etc) for each nsIDOMNode.
|
|
* All nsXFormsMDGNodes for same nsIDOMNode are linked together via 'next'.
|
|
*/
|
|
class nsXFormsMDGNode {
|
|
private:
|
|
/** Dirty flag */
|
|
PRBool mDirty;
|
|
|
|
/** Does this node have an XPath expression attached to it */
|
|
PRBool mHasExpr;
|
|
|
|
public:
|
|
/** Pointer to the nsIDOMNode */
|
|
nsCOMPtr<nsIDOMNode> mContextNode;
|
|
|
|
/** The XPath expression for this node */
|
|
nsCOMPtr<nsIDOMXPathExpression> mExpression;
|
|
|
|
/** List of nodes that depend on this node */
|
|
nsVoidArray mSuc;
|
|
|
|
/** Number of nodes that this node depends on */
|
|
unsigned int mCount;
|
|
|
|
/** The type */
|
|
ModelItemPropName mType;
|
|
|
|
/** (XPath) Context size for this node */
|
|
PRInt32 mContextSize;
|
|
|
|
/** (XPath) Position for this node */
|
|
PRInt32 mContextPosition;
|
|
|
|
/** Does expression use dynamic functions */
|
|
PRBool mDynFunc;
|
|
|
|
/** Pointer to next nsXFormsMDGNode with same nsIDOMNode, but different type */
|
|
nsXFormsMDGNode* mNext;
|
|
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param aNode The context node
|
|
* @param aType The type of node (calculate, readonly, etc.)
|
|
*/
|
|
nsXFormsMDGNode(nsIDOMNode* aNode, const ModelItemPropName aType);
|
|
|
|
/** Destructor */
|
|
~nsXFormsMDGNode();
|
|
|
|
/**
|
|
* Sets the XPath expression for the node.
|
|
*
|
|
* @param aExpression The XPath expression
|
|
* @param aDynFunc Whether expression uses dynamic functions
|
|
* @param aContextPosition The context position for the expression
|
|
* @param aContextSize The context size for the expression
|
|
*/
|
|
void SetExpression(nsIDOMXPathExpression* aExpression, PRBool aDynFunc,
|
|
PRInt32 aContextPosition, PRInt32 aContextSize);
|
|
|
|
/** Does node have an expression? */
|
|
PRBool HasExpr() const;
|
|
|
|
/** Is node dirty? */
|
|
PRBool IsDirty() const;
|
|
|
|
/* Mark node clean */
|
|
void MarkClean();
|
|
|
|
/* Mark node dirty */
|
|
void MarkDirty();
|
|
};
|
|
|
|
|
|
/**
|
|
* The Multi Dependency Graph (MDG) Engine.
|
|
*
|
|
* This class handles all the necessary logic to create and maintain the MDG,
|
|
* and update the instance data accordingly.
|
|
*
|
|
* A bit about the graph:
|
|
* As specified in the spec., one node (nsXFormsMDGNode) is created in the graph for
|
|
* each of the attributes (readonly, calculate, etc.) for a nsIDOMNode. These graph
|
|
* nodes are owned by the mNodeToMDG hash table, which maps from a nsIDOMNode to
|
|
* the first node in a single-linked list (mNext) of nodes for the same nsIDOMNode.
|
|
*/
|
|
class nsXFormsMDGEngine
|
|
{
|
|
protected:
|
|
/**
|
|
* Maps from nsIDOMNode to nsXFormsMDGNode(s)
|
|
*/
|
|
nsClassHashtable<nsISupportsHashKey, nsXFormsMDGNode> mNodeToMDG;
|
|
|
|
/**
|
|
* Maps from nsIDOMNode to flag (MDG_FLAG_*)
|
|
*/
|
|
nsDataHashtable<nsISupportsHashKey, PRUint16> mNodeToFlag;
|
|
|
|
/**
|
|
* True when Rebuild() has been run, but not ClearDispatchFlags()
|
|
*/
|
|
PRBool mJustRebuilt;
|
|
|
|
/**
|
|
* True when last Calculate() was run when mJustRebuilded was true.
|
|
*/
|
|
PRBool mFirstCalculate;
|
|
|
|
/** The actual MDG */
|
|
nsVoidArray mGraph;
|
|
|
|
/** Set of nodes that are marked as changed, and should be included in recalculation */
|
|
nsXFormsMDGSet mMarkedNodes;
|
|
|
|
/** Number of nodes in the graph */
|
|
PRInt32 mNodesInGraph;
|
|
|
|
/** Hidden copy constructor */
|
|
nsXFormsMDGEngine(nsXFormsMDGEngine&) {}
|
|
|
|
/**
|
|
* Used by Clear() and ~ to delete the linked nodes in mNodeToMDG, the hash table
|
|
* itself handles the main nodes.
|
|
*/
|
|
static PLDHashOperator PR_CALLBACK DeleteLinkedNodes(nsISupports *aKey, nsAutoPtr<nsXFormsMDGNode>& aNode, void* aArg);
|
|
|
|
/**
|
|
* Used by Rebuild() to find the start nodes for mGraph, that is nodes
|
|
* where mCount == 0.
|
|
*/
|
|
static PLDHashOperator PR_CALLBACK AddStartNodes(nsISupports *aKey, nsXFormsMDGNode* aNode, void* aDeque);
|
|
|
|
/**
|
|
* Used by AndFlags() to boolean AND all flags with aMask.
|
|
*/
|
|
static PLDHashOperator PR_CALLBACK AndFlag(nsISupports *aKey, PRUint16& aFlag, void* aMask);
|
|
|
|
/**
|
|
* Inserts a new text child for aContextNode.
|
|
*
|
|
* @param aContextNode The node to create a child for
|
|
* @param aNodeValue The value of the new node
|
|
* @param aBeforeNode If non-null, insert new node before this node
|
|
*/
|
|
nsresult CreateNewChild(nsIDOMNode* aContextNode, const nsAString& aNodeValue, nsIDOMNode* aBeforeNode = nsnull);
|
|
|
|
/**
|
|
* Retrieve a node from the graph.
|
|
*
|
|
* @param aDomNode The DOM node to retrieve
|
|
* @param aType The type to retrieve (readonly, calculate, etc)
|
|
* @param aCreate Create the node and insert it into the graph if it does not exist?
|
|
* @return The node, nsnull if not found and aCreate != PR_TRUE
|
|
*/
|
|
nsXFormsMDGNode* GetNode(nsIDOMNode* aDomNode, ModelItemPropName aType, PRBool aCreate = PR_TRUE);
|
|
|
|
/**
|
|
* Sets the flag for a node.
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aFlag The flag
|
|
*/
|
|
void SetFlag(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
|
|
|
/**
|
|
* Boolean OR the existing flag on the node with a new flag
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aFlag The new flag
|
|
*/
|
|
void OrFlag(nsIDOMNode* aDomNode, PRInt16 aFlag);
|
|
|
|
/**
|
|
* Retrieve the flag for a node.
|
|
*
|
|
* @param aDomNode The node
|
|
* @return The flag
|
|
*/
|
|
PRUint16 GetFlag(nsIDOMNode* aDomNode);
|
|
|
|
/**
|
|
* Sets a bit in the flag for a node
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aBit The bit position to set
|
|
* @param aOn The bit value
|
|
*/
|
|
void SetFlagBits(nsIDOMNode* aDomNode, PRUint16 aBit, PRBool aOn);
|
|
|
|
/**
|
|
* Boolean AND all flags with a mask.
|
|
*
|
|
* @param aAndMask The mask
|
|
* @return Did operation succeed?
|
|
*/
|
|
PRBool AndFlags(PRUint16 aAndMask);
|
|
|
|
/**
|
|
* Evaluates the expression for the given node and returns the boolean result.
|
|
*
|
|
* @param aNode The node to evaluate
|
|
* @param res The result of the evaluation
|
|
*/
|
|
nsresult BooleanExpression(nsXFormsMDGNode* aNode, PRBool& res);
|
|
|
|
/**
|
|
* Compute MIP value for node types with boolean result (all except calculate)
|
|
*
|
|
* @param aStateFlag The flag for the type of MIP
|
|
* @param aDispatchFlag The dispatch flag
|
|
* @param aNode The context node
|
|
* @param aDidChange Was the node changed?
|
|
*/
|
|
nsresult ComputeMIP(PRUint16 aStateFlag, PRUint16 aDispatchFlag, nsXFormsMDGNode* aNode, PRBool& aDidChange);
|
|
|
|
/**
|
|
* Same as ComputeMIP(), but also handles any inheritance of attributes.
|
|
*
|
|
* @param aStateFlag The flag for the type of MIP
|
|
* @param aDispatchFlag The dispatch flag
|
|
* @param aInheritanceFlag The inheritance flag for the type of MIP
|
|
* @param aNode The context node
|
|
* @param aSet Set of the nodes influenced by operation
|
|
*/
|
|
nsresult ComputeMIPWithInheritance(PRUint16 aStateFlag, PRUint16 aDispatchFlag, PRUint16 aInheritanceFlag, nsXFormsMDGNode* aNode, nsXFormsMDGSet* aSet);
|
|
|
|
/**
|
|
* Attaches inheritance to all children of a given node
|
|
*
|
|
* @param aSet Set of the nodes influenced by operation
|
|
* @param aSrc The node
|
|
* @param aState The state of the flag
|
|
* @param aStateFlag The flag
|
|
*/
|
|
nsresult AttachInheritance(nsXFormsMDGSet* aSet, nsIDOMNode* aSrc, PRBool aState, PRUint16 aStateFlag);
|
|
|
|
/**
|
|
* Invalidate the information, ie. mark all nodes as dirty.
|
|
*/
|
|
nsresult Invalidate();
|
|
|
|
/**
|
|
* Get flag value for node and clear flag.
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aFlag The flag
|
|
* @return The flag value
|
|
*/
|
|
PRBool TestAndClear(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
|
|
|
/**
|
|
* Get flag value for node and set flag.
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aFlag The flag
|
|
* @return The flag value
|
|
*/
|
|
PRBool TestAndSet(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
|
|
|
/**
|
|
* Get flag value for node
|
|
*
|
|
* @param aDomNode The node
|
|
* @param aFlag The flag
|
|
* @return The flag value
|
|
*/
|
|
PRBool Test(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
|
|
|
public:
|
|
/**
|
|
* Constructor
|
|
*/
|
|
nsXFormsMDGEngine();
|
|
|
|
/**
|
|
* Destructor
|
|
*/
|
|
~nsXFormsMDGEngine();
|
|
|
|
/**
|
|
* Initializes the internal structures. Needs to be called before class is used!
|
|
*/
|
|
nsresult Init();
|
|
|
|
/**
|
|
* Insert new MIP (Model Item Property) into graph.
|
|
*
|
|
* @param aType The type of MIP
|
|
* @param aExpression The XPath expression
|
|
* @param aDependencies Set of nodes expression depends on
|
|
* @param aDynFunc True if expression uses dynamic functions
|
|
* @param aContextNode The context node for aExpression
|
|
* @param aContextPos The context positions of aExpression
|
|
* @param aContextSize The context size for aExpression
|
|
*/
|
|
/* void addMIP (in long aType, in nsIDOMXPathExpression aExpression, in nsXFormsMDGSet aDependencies, in boolean aDynFunc, in nsIDOMNode aContextNode, in long aContextPos, in long aContextSize); */
|
|
nsresult AddMIP(PRInt32 aType, nsIDOMXPathExpression *aExpression, nsXFormsMDGSet *aDependencies, PRBool aDynFunc, nsIDOMNode *aContextNode, PRInt32 aContextPos, PRInt32 aContextSize);
|
|
|
|
/**
|
|
* Recalculate the MDG.
|
|
*
|
|
* @param aChangedNodes Returns the nodes that was changed during recalculation.
|
|
*/
|
|
nsresult Recalculate(nsXFormsMDGSet **aChangedNodes);
|
|
|
|
/**
|
|
* Rebuilds the MDG.
|
|
*/
|
|
nsresult Rebuild();
|
|
|
|
/**
|
|
* Clears all information in the MDG.
|
|
*/
|
|
nsresult Clear();
|
|
|
|
/**
|
|
* Clears all Dispatch flags.
|
|
*/
|
|
nsresult ClearDispatchFlags();
|
|
|
|
/**
|
|
* Mark a node as changed.
|
|
*
|
|
* @param aContextNode The node to be marked.
|
|
*/
|
|
nsresult MarkNodeAsChanged(nsIDOMNode *aContextNode);
|
|
|
|
/**
|
|
* Set the value of a node. (used by nsXFormsMDG)
|
|
|
|
* @param aContextNode The node to set the value for
|
|
* @param aNodeValue The value
|
|
* @param aMarkNode Whether to mark node as changed
|
|
* @param aNodeChanged Was node changed?
|
|
*/
|
|
nsresult SetNodeValue(nsIDOMNode *aContextNode, const nsAString & aNodeValue, PRBool aMarkNode, PRBool *aNodeChanged);
|
|
|
|
/**
|
|
* Get the value of a node. (used by nsXFormsMDG)
|
|
|
|
* @param aContextNode The node to get the value for
|
|
* @param aNodeValue The value of the node
|
|
*/
|
|
nsresult GetNodeValue(nsIDOMNode *aContextNode, nsAString & aNodeValue);
|
|
|
|
PRBool IsConstraint(nsIDOMNode *aContextNode);
|
|
|
|
PRBool IsValid(nsIDOMNode *aContextNode);
|
|
|
|
PRBool ShouldDispatchValid(nsIDOMNode *aContextNode);
|
|
|
|
PRBool IsReadonly(nsIDOMNode *aContextNode);
|
|
|
|
PRBool ShouldDispatchReadonly(nsIDOMNode *aContextNode);
|
|
|
|
PRBool IsRelevant(nsIDOMNode *aContextNode);
|
|
|
|
PRBool ShouldDispatchRelevant(nsIDOMNode *aContextNode);
|
|
|
|
PRBool IsRequired(nsIDOMNode *aContextNode);
|
|
|
|
PRBool ShouldDispatchRequired(nsIDOMNode *aContextNode);
|
|
|
|
PRBool ShouldDispatchValueChanged(nsIDOMNode *aContextNode);
|
|
};
|
|
|
|
#endif
|