LCOV - code coverage report
Current view: directory - content/xul/templates/src - nsXULTemplateBuilder.h (source / functions) Found Hit Coverage
Test: app.info Lines: 18 1 5.6 %
Date: 2012-06-02 Functions: 12 1 8.3 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Robert Churchill <rjc@netscape.com>
      24                 :  *   David Hyatt <hyatt@netscape.com>
      25                 :  *   Chris Waterson <waterson@netscape.com>
      26                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      27                 :  *   Neil Deakin <enndeakin@sympatico.ca>
      28                 :  *
      29                 :  * Alternatively, the contents of this file may be used under the terms of
      30                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      31                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      32                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      33                 :  * of those above. If you wish to allow use of your version of this file only
      34                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      35                 :  * use your version of this file under the terms of the MPL, indicate your
      36                 :  * decision by deleting the provisions above and replace them with the notice
      37                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      38                 :  * the provisions above, a recipient may use your version of this file under
      39                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      40                 :  *
      41                 :  * ***** END LICENSE BLOCK ***** */
      42                 : 
      43                 : #ifndef nsXULTemplateBuilder_h__
      44                 : #define nsXULTemplateBuilder_h__
      45                 : 
      46                 : #include "nsStubDocumentObserver.h"
      47                 : #include "nsIScriptSecurityManager.h"
      48                 : #include "nsIContent.h"
      49                 : #include "nsIObserver.h"
      50                 : #include "nsIRDFCompositeDataSource.h"
      51                 : #include "nsIRDFContainer.h"
      52                 : #include "nsIRDFContainerUtils.h"
      53                 : #include "nsIRDFDataSource.h"
      54                 : #include "nsIRDFObserver.h"
      55                 : #include "nsIRDFService.h"
      56                 : #include "nsIXULTemplateBuilder.h"
      57                 : 
      58                 : #include "nsFixedSizeAllocator.h"
      59                 : #include "nsCOMArray.h"
      60                 : #include "nsTArray.h"
      61                 : #include "nsDataHashtable.h"
      62                 : #include "nsTemplateRule.h"
      63                 : #include "nsTemplateMatch.h"
      64                 : #include "nsIXULTemplateQueryProcessor.h"
      65                 : #include "nsCycleCollectionParticipant.h"
      66                 : 
      67                 : #include "prlog.h"
      68                 : #ifdef PR_LOGGING
      69                 : extern PRLogModuleInfo* gXULTemplateLog;
      70                 : #endif
      71                 : 
      72                 : class nsIXULDocument;
      73                 : class nsIRDFCompositeDataSource;
      74                 : class nsIObserverService;
      75                 : 
      76                 : /**
      77                 :  * An object that translates an RDF graph into a presentation using a
      78                 :  * set of rules.
      79                 :  */
      80                 : class nsXULTemplateBuilder : public nsIXULTemplateBuilder,
      81                 :                              public nsIObserver,
      82                 :                              public nsStubDocumentObserver
      83                 : {
      84                 : public:
      85                 :     nsXULTemplateBuilder();
      86                 :     virtual ~nsXULTemplateBuilder();
      87                 : 
      88                 :     nsresult InitGlobals();
      89                 : 
      90                 :     /**
      91                 :      * Clear the template builder structures. The aIsFinal flag is set to true
      92                 :      * when the template is going away.
      93                 :      */
      94                 :     virtual void Uninit(bool aIsFinal);
      95                 : 
      96                 :     // nsISupports interface
      97               0 :     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
      98            2928 :     NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXULTemplateBuilder,
      99                 :                                              nsIXULTemplateBuilder)
     100                 : 
     101                 :     // nsIXULTemplateBuilder interface
     102                 :     NS_DECL_NSIXULTEMPLATEBUILDER
     103                 : 
     104                 :     // nsIObserver Interface
     105                 :     NS_DECL_NSIOBSERVER
     106                 : 
     107                 :     // nsIMutationObserver
     108                 :     NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
     109                 :     NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
     110                 :     NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
     111                 : 
     112                 :     /**
     113                 :      * Remove an old result and/or add a new result. This method will retrieve
     114                 :      * the set of containers where the result could be inserted and either add
     115                 :      * the new result to those containers, or remove the result from those
     116                 :      * containers. UpdateResultInContainer is called for each container.
     117                 :      *
     118                 :      * @param aOldResult result to remove
     119                 :      * @param aNewResult result to add
     120                 :      * @param aQueryNode query node for new result
     121                 :      */
     122                 :     nsresult
     123                 :     UpdateResult(nsIXULTemplateResult* aOldResult,
     124                 :                  nsIXULTemplateResult* aNewResult,
     125                 :                  nsIDOMNode* aQueryNode);
     126                 : 
     127                 :     /**
     128                 :      * Remove an old result and/or add a new result from a specific container.
     129                 :      *
     130                 :      * @param aOldResult result to remove
     131                 :      * @param aNewResult result to add
     132                 :      * @param aQueryNode queryset for the new result
     133                 :      * @param aOldId id of old result
     134                 :      * @param aNewId id of new result
     135                 :      * @param aInsertionPoint container to remove or add result inside
     136                 :      */
     137                 :     nsresult
     138                 :     UpdateResultInContainer(nsIXULTemplateResult* aOldResult,
     139                 :                             nsIXULTemplateResult* aNewResult,
     140                 :                             nsTemplateQuerySet* aQuerySet,
     141                 :                             nsIRDFResource* aOldId,
     142                 :                             nsIRDFResource* aNewId,
     143                 :                             nsIContent* aInsertionPoint);
     144                 : 
     145                 :     nsresult
     146                 :     ComputeContainmentProperties();
     147                 : 
     148                 :     static bool
     149                 :     IsTemplateElement(nsIContent* aContent);
     150                 : 
     151                 :     virtual nsresult
     152                 :     RebuildAll() = 0; // must be implemented by subclasses
     153                 : 
     154               0 :     void RunnableRebuild() { Rebuild(); }
     155               0 :     void RunnableLoadAndRebuild() {
     156               0 :       Uninit(false);  // Reset results
     157                 : 
     158               0 :       nsCOMPtr<nsIDocument> doc = mRoot ? mRoot->GetDocument() : nsnull;
     159               0 :       if (doc) {
     160                 :         bool shouldDelay;
     161               0 :         LoadDataSources(doc, &shouldDelay);
     162               0 :         if (!shouldDelay) {
     163               0 :           Rebuild();
     164                 :         }
     165                 :       }
     166               0 :     }
     167                 : 
     168                 :     // mRoot should not be cleared until after Uninit is finished so that
     169                 :     // generated content can be removed during uninitialization.
     170               0 :     void UninitFalse() { Uninit(false); mRoot = nsnull; }
     171               0 :     void UninitTrue() { Uninit(true); mRoot = nsnull; }
     172                 : 
     173                 :     /**
     174                 :      * Find the <template> tag that applies for this builder
     175                 :      */
     176                 :     nsresult
     177                 :     GetTemplateRoot(nsIContent** aResult);
     178                 : 
     179                 :     /**
     180                 :      * Compile the template's queries
     181                 :      */
     182                 :     nsresult
     183                 :     CompileQueries();
     184                 : 
     185                 :     /**
     186                 :      * Compile the template given a <template> in aTemplate. This function
     187                 :      * is called recursively to handle queries inside a queryset. For the
     188                 :      * outer pass, aIsQuerySet will be false, while the inner pass this will
     189                 :      * be true.
     190                 :      *
     191                 :      * aCanUseTemplate will be set to true if the template's queries could be
     192                 :      * compiled, and false otherwise. If false, the entire template is
     193                 :      * invalid.
     194                 :      *
     195                 :      * @param aTemplate <template> to compile
     196                 :      * @param aQuerySet first queryset
     197                 :      * @param aIsQuerySet true if 
     198                 :      * @param aPriority the queryset index, incremented when a new one is added
     199                 :      * @param aCanUseTemplate true if template is valid
     200                 :      */
     201                 :     nsresult
     202                 :     CompileTemplate(nsIContent* aTemplate,
     203                 :                     nsTemplateQuerySet* aQuerySet,
     204                 :                     bool aIsQuerySet,
     205                 :                     PRInt32* aPriority,
     206                 :                     bool* aCanUseTemplate);
     207                 : 
     208                 :     /**
     209                 :      * Compile a query using the extended syntax. For backwards compatible RDF
     210                 :      * syntax where there is no <query>, the <conditions> becomes the query.
     211                 :      *
     212                 :      * @param aRuleElement <rule> element
     213                 :      * @param aActionElement <action> element
     214                 :      * @param aMemberVariable member variable for the query
     215                 :      * @param aQuerySet the queryset
     216                 :      */
     217                 :     nsresult 
     218                 :     CompileExtendedQuery(nsIContent* aRuleElement,
     219                 :                          nsIContent* aActionElement,
     220                 :                          nsIAtom* aMemberVariable,
     221                 :                          nsTemplateQuerySet* aQuerySet);
     222                 : 
     223                 :     /**
     224                 :      * Determine the ref variable and tag from inside a RDF query.
     225                 :      */
     226                 :     void DetermineRDFQueryRef(nsIContent* aQueryElement, nsIAtom** tag);
     227                 : 
     228                 :     /**
     229                 :      * Determine the member variable from inside an action body. It will be
     230                 :      * the value of the uri attribute on a node.
     231                 :      */
     232                 :     already_AddRefed<nsIAtom> DetermineMemberVariable(nsIContent* aElement);
     233                 : 
     234                 :     /**
     235                 :      * Compile a simple query. A simple query is one that doesn't have a
     236                 :      * <query> and should use a default query which would normally just return
     237                 :      * a list of children of the reference point.
     238                 :      *
     239                 :      * @param aRuleElement the <rule>
     240                 :      * @param aQuerySet the query set
     241                 :      * @param aCanUseTemplate true if the query is valid
     242                 :      */
     243                 :     nsresult 
     244                 :     CompileSimpleQuery(nsIContent* aRuleElement,
     245                 :                        nsTemplateQuerySet* aQuerySet,
     246                 :                        bool* aCanUseTemplate);
     247                 : 
     248                 :     /**
     249                 :      * Compile the <conditions> tag in a rule
     250                 :      *
     251                 :      * @param aRule template rule
     252                 :      * @param aConditions <conditions> element
     253                 :      */
     254                 :     nsresult
     255                 :     CompileConditions(nsTemplateRule* aRule, nsIContent* aConditions);
     256                 : 
     257                 :     /**
     258                 :      * Compile a <where> tag in a condition. The caller should set
     259                 :      * *aCurrentCondition to null for the first condition. This value will be
     260                 :      * updated to point to the new condition before returning. The conditions
     261                 :      * will be added to the rule aRule by this method.
     262                 :      *
     263                 :      * @param aRule template rule
     264                 :      * @param aCondition <where> element
     265                 :      * @param aCurrentCondition compiled condition
     266                 :      */
     267                 :     nsresult
     268                 :     CompileWhereCondition(nsTemplateRule* aRule,
     269                 :                           nsIContent* aCondition,
     270                 :                           nsTemplateCondition** aCurrentCondition);
     271                 : 
     272                 :     /**
     273                 :      * Compile the <bindings> for an extended template syntax rule.
     274                 :      */
     275                 :     nsresult
     276                 :     CompileBindings(nsTemplateRule* aRule, nsIContent* aBindings);
     277                 : 
     278                 :     /**
     279                 :      * Compile a single binding for an extended template syntax rule.
     280                 :      */
     281                 :     nsresult
     282                 :     CompileBinding(nsTemplateRule* aRule, nsIContent* aBinding);
     283                 : 
     284                 :     /**
     285                 :      * Add automatic bindings for simple rules
     286                 :      */
     287                 :     nsresult
     288                 :     AddSimpleRuleBindings(nsTemplateRule* aRule, nsIContent* aElement);
     289                 : 
     290                 :     static void
     291                 :     AddBindingsFor(nsXULTemplateBuilder* aSelf,
     292                 :                    const nsAString& aVariable,
     293                 :                    void* aClosure);
     294                 : 
     295                 :     /**
     296                 :      * Load the datasources for the template. shouldDelayBuilding is an out
     297                 :      * parameter which will be set to true to indicate that content building
     298                 :      * should not be performed yet as the datasource has not yet loaded. If
     299                 :      * false, the datasource has already loaded so building can proceed
     300                 :      * immediately. In the former case, the datasource or query processor
     301                 :      * should either rebuild the template or update results when the
     302                 :      * datasource is loaded as needed.
     303                 :      */
     304                 :     nsresult
     305                 :     LoadDataSources(nsIDocument* aDoc, bool* shouldDelayBuilding);
     306                 : 
     307                 :     /**
     308                 :      * Called by LoadDataSources to load a datasource given a uri list
     309                 :      * in aDataSource. The list is a set of uris separated by spaces.
     310                 :      * If aIsRDFQuery is true, then this is for an RDF datasource which
     311                 :      * causes the method to check for additional flags specific to the
     312                 :      * RDF processor.
     313                 :      */
     314                 :     nsresult
     315                 :     LoadDataSourceUrls(nsIDocument* aDocument,
     316                 :                        const nsAString& aDataSources,
     317                 :                        bool aIsRDFQuery,
     318                 :                        bool* aShouldDelayBuilding);
     319                 : 
     320                 :     nsresult
     321                 :     InitHTMLTemplateRoot();
     322                 : 
     323                 :     /**
     324                 :      * Determine which rule matches a given result. aContainer is used for
     325                 :      * tag matching and is optional for non-content generating builders.
     326                 :      * The returned matched rule is always one of the rules owned by the
     327                 :      * query set aQuerySet.
     328                 :      *
     329                 :      * @param aContainer parent where generated content will be inserted
     330                 :      * @param aResult result to match
     331                 :      * @param aQuerySet query set to examine the rules of
     332                 :      * @param aMatchedRule [out] rule that has matched, or null if any.
     333                 :      * @param aRuleIndex [out] index of the rule
     334                 :      */
     335                 :     nsresult
     336                 :     DetermineMatchedRule(nsIContent* aContainer,
     337                 :                          nsIXULTemplateResult* aResult,
     338                 :                          nsTemplateQuerySet* aQuerySet,
     339                 :                          nsTemplateRule** aMatchedRule,
     340                 :                          PRInt16 *aRuleIndex);
     341                 : 
     342                 :     // XXX sigh, the string template foo doesn't mix with
     343                 :     // operator->*() on egcs-1.1.2, so we'll need to explicitly pass
     344                 :     // "this" and use good ol' fashioned static callbacks.
     345                 :     void
     346                 :     ParseAttribute(const nsAString& aAttributeValue,
     347                 :                    void (*aVariableCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
     348                 :                    void (*aTextCallback)(nsXULTemplateBuilder* aThis, const nsAString&, void*),
     349                 :                    void* aClosure);
     350                 : 
     351                 :     nsresult
     352                 :     SubstituteText(nsIXULTemplateResult* aMatch,
     353                 :                    const nsAString& aAttributeValue,
     354                 :                    nsAString& aResult);
     355                 : 
     356                 :     static void
     357                 :     SubstituteTextAppendText(nsXULTemplateBuilder* aThis, const nsAString& aText, void* aClosure);
     358                 : 
     359                 :     static void
     360                 :     SubstituteTextReplaceVariable(nsXULTemplateBuilder* aThis, const nsAString& aVariable, void* aClosure);    
     361                 : 
     362                 :     nsresult 
     363                 :     IsSystemPrincipal(nsIPrincipal *principal, bool *result);
     364                 : 
     365                 :     /**
     366                 :      * Convenience method which gets a resource for a result. If a result
     367                 :      * doesn't have a resource set, it will create one from the result's id.
     368                 :      */
     369                 :     nsresult GetResultResource(nsIXULTemplateResult* aResult,
     370                 :                                nsIRDFResource** aResource);
     371                 : 
     372                 : protected:
     373                 :     nsCOMPtr<nsISupports> mDataSource;
     374                 :     nsCOMPtr<nsIRDFDataSource> mDB;
     375                 :     nsCOMPtr<nsIRDFCompositeDataSource> mCompDB;
     376                 : 
     377                 :     /**
     378                 :      * Circular reference, broken when the document is destroyed.
     379                 :      */
     380                 :     nsCOMPtr<nsIContent> mRoot;
     381                 : 
     382                 :     /**
     383                 :      * The root result, translated from the root element's ref
     384                 :      */
     385                 :     nsCOMPtr<nsIXULTemplateResult> mRootResult;
     386                 : 
     387                 :     nsCOMArray<nsIXULBuilderListener> mListeners;
     388                 : 
     389                 :     /**
     390                 :      * The query processor which generates results
     391                 :      */
     392                 :     nsCOMPtr<nsIXULTemplateQueryProcessor> mQueryProcessor;
     393                 : 
     394                 :     /**
     395                 :      * The list of querysets
     396                 :      */
     397                 :     nsTArray<nsTemplateQuerySet *> mQuerySets;
     398                 : 
     399                 :     /**
     400                 :      * Set to true if the rules have already been compiled
     401                 :      */
     402                 :     bool          mQueriesCompiled;
     403                 : 
     404                 :     /**
     405                 :      * The default reference and member variables.
     406                 :      */
     407                 :     nsCOMPtr<nsIAtom> mRefVariable;
     408                 :     nsCOMPtr<nsIAtom> mMemberVariable;
     409                 : 
     410                 :     /**
     411                 :      * The match map contains nsTemplateMatch objects, one for each unique
     412                 :      * match found, keyed by the resource for that match. A particular match
     413                 :      * will contain a linked list of all of the matches for that unique result
     414                 :      * id. Only one is active at a time. When a match is retracted, look in
     415                 :      * the match map, remove it, and apply the next valid match in sequence to
     416                 :      * make active.
     417                 :      */
     418                 :     nsDataHashtable<nsISupportsHashKey, nsTemplateMatch*> mMatchMap;
     419                 : 
     420                 :     /**
     421                 :      * Fixed size allocator used to allocate matches
     422                 :      */
     423                 :     nsFixedSizeAllocator mPool;
     424                 : 
     425                 : public:
     426                 : 
     427                 :     nsFixedSizeAllocator& GetPool() { return mPool; }
     428                 : 
     429                 : protected:
     430                 :     // pseudo-constants
     431                 :     static nsrefcnt gRefCnt;
     432                 :     static nsIRDFService*            gRDFService;
     433                 :     static nsIRDFContainerUtils*     gRDFContainerUtils;
     434                 :     static nsIScriptSecurityManager* gScriptSecurityManager;
     435                 :     static nsIPrincipal*             gSystemPrincipal;
     436                 :     static nsIObserverService*       gObserverService;
     437                 : 
     438                 :     enum {
     439                 :         eDontTestEmpty = (1 << 0),
     440                 :         eDontRecurse = (1 << 1),
     441                 :         eLoggingEnabled = (1 << 2)
     442                 :     };
     443                 : 
     444                 :     PRInt32 mFlags;
     445                 : 
     446                 :     /**
     447                 :      * Stack-based helper class to maintain a list of ``activated''
     448                 :      * resources; i.e., resources for which we are currently building
     449                 :      * content.
     450                 :      */
     451                 :     class ActivationEntry {
     452                 :     public:
     453                 :         nsIRDFResource   *mResource;
     454                 :         ActivationEntry  *mPrevious;
     455                 :         ActivationEntry **mLink;
     456                 : 
     457               0 :         ActivationEntry(nsIRDFResource *aResource, ActivationEntry **aLink)
     458                 :             : mResource(aResource),
     459                 :               mPrevious(*aLink),
     460               0 :               mLink(aLink) { *mLink = this; }
     461                 : 
     462               0 :         ~ActivationEntry() { *mLink = mPrevious; }
     463                 :     };
     464                 : 
     465                 :     /**
     466                 :      * The top of the stack of resources that we're currently building
     467                 :      * content for.
     468                 :      */
     469                 :     ActivationEntry *mTop;
     470                 : 
     471                 :     /**
     472                 :      * Determine if a resource is currently on the activation stack.
     473                 :      */
     474                 :     bool
     475                 :     IsActivated(nsIRDFResource *aResource);
     476                 : 
     477                 :     /**
     478                 :      * Returns true if content may be generated for a result, or false if it
     479                 :      * cannot, for example, if it would be created inside a closed container.
     480                 :      * Those results will be generated when the container is opened.
     481                 :      * If false is returned, no content should be generated. Possible 
     482                 :      * insertion locations may optionally be set for new content, depending on
     483                 :      * the builder being used. Note that *aLocations or some items within
     484                 :      * aLocations may be null.
     485                 :      */
     486                 :     virtual bool
     487                 :     GetInsertionLocations(nsIXULTemplateResult* aResult,
     488                 :                           nsCOMArray<nsIContent>** aLocations) = 0;
     489                 : 
     490                 :     /**
     491                 :      * Must be implemented by subclasses. Handle removing the generated
     492                 :      * output for aOldMatch and adding new output for aNewMatch. Either
     493                 :      * aOldMatch or aNewMatch may be null. aContext is the location returned
     494                 :      * from the call to MayGenerateResult.
     495                 :      */
     496                 :     virtual nsresult
     497                 :     ReplaceMatch(nsIXULTemplateResult* aOldResult,
     498                 :                  nsTemplateMatch* aNewMatch,
     499                 :                  nsTemplateRule* aNewMatchRule,
     500                 :                  void *aContext) = 0;
     501                 : 
     502                 :     /**
     503                 :      * Must be implemented by subclasses. Handle change in bound
     504                 :      * variable values for aResult. aModifiedVars contains the set
     505                 :      * of variables that have changed.
     506                 :      * @param aResult the ersult for which variable bindings has changed.
     507                 :      * @param aModifiedVars the set of variables for which the bindings
     508                 :      * have changed.
     509                 :      */
     510                 :     virtual nsresult
     511                 :     SynchronizeResult(nsIXULTemplateResult* aResult) = 0;
     512                 : 
     513                 :     /**
     514                 :      * Output a new match or removed match to the console.
     515                 :      *
     516                 :      * @param aId id of the result
     517                 :      * @param aMatch new or removed match
     518                 :      * @param aIsNew true for new matched, false for removed matches
     519                 :      */
     520                 :     void
     521                 :     OutputMatchToLog(nsIRDFResource* aId,
     522                 :                      nsTemplateMatch* aMatch,
     523                 :                      bool aIsNew);
     524                 : 
     525               0 :     virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const
     526                 :     {
     527               0 :     }
     528                 : 
     529                 :     /**
     530                 :      * Document that we're observing. Weak ref!
     531                 :      */
     532                 :     nsIDocument* mObservedDocument;
     533                 : };
     534                 : 
     535                 : #endif // nsXULTemplateBuilder_h__

Generated by: LCOV version 1.7