LCOV - code coverage report
Current view: directory - rdf/base/src - nsRDFContainer.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 298 168 56.4 %
Date: 2012-06-02 Functions: 22 18 81.8 %

       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                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      27                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : /*
      40                 : 
      41                 :   Implementation for the RDF container.
      42                 : 
      43                 :   Notes
      44                 :   -----
      45                 : 
      46                 :   1. RDF containers are one-indexed. This means that a lot of the loops
      47                 :      that you'd normally think you'd write like this:
      48                 : 
      49                 :        for (i = 0; i < count; ++i) {}
      50                 : 
      51                 :      You've gotta write like this:
      52                 : 
      53                 :        for (i = 1; i <= count; ++i) {}
      54                 : 
      55                 :      "Sure, right, yeah, of course.", you say. Well maybe I'm just
      56                 :      thick, but it's easy to slip up.
      57                 : 
      58                 :   2. The RDF:nextVal property on the container is an
      59                 :      implementation-level hack that is used to quickly compute the
      60                 :      next value for appending to the container. It will no doubt
      61                 :      become royally screwed up in the case of aggregation.
      62                 : 
      63                 :   3. The RDF:nextVal property is also used to retrieve the count of
      64                 :      elements in the container.
      65                 : 
      66                 :  */
      67                 : 
      68                 : 
      69                 : #include "nsCOMPtr.h"
      70                 : #include "nsIRDFContainer.h"
      71                 : #include "nsIRDFContainerUtils.h"
      72                 : #include "nsIRDFInMemoryDataSource.h"
      73                 : #include "nsIRDFPropagatableDataSource.h"
      74                 : #include "nsIRDFService.h"
      75                 : #include "nsIServiceManager.h"
      76                 : #include "nsRDFCID.h"
      77                 : #include "nsString.h"
      78                 : #include "nsXPIDLString.h"
      79                 : #include "rdf.h"
      80                 : 
      81                 : static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
      82                 : static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
      83                 : static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
      84                 : 
      85                 : #define RDF_SEQ_LIST_LIMIT   8
      86                 : 
      87                 : class RDFContainerImpl : public nsIRDFContainer
      88                 : {
      89                 : public:
      90                 : 
      91                 :     // nsISupports interface
      92                 :     NS_DECL_ISUPPORTS
      93                 : 
      94                 :     // nsIRDFContainer interface
      95                 :     NS_DECL_NSIRDFCONTAINER
      96                 : 
      97                 : private:
      98                 :     friend nsresult NS_NewRDFContainer(nsIRDFContainer** aResult);
      99                 : 
     100                 :     RDFContainerImpl();
     101                 :     virtual ~RDFContainerImpl();
     102                 : 
     103                 :     nsresult Init();
     104                 : 
     105                 :     nsresult Renumber(PRInt32 aStartIndex, PRInt32 aIncrement);
     106                 :     nsresult SetNextValue(PRInt32 aIndex);
     107                 :     nsresult GetNextValue(nsIRDFResource** aResult);
     108                 :     
     109                 :     nsIRDFDataSource* mDataSource;
     110                 :     nsIRDFResource*   mContainer;
     111                 : 
     112                 :     // pseudo constants
     113                 :     static PRInt32 gRefCnt;
     114                 :     static nsIRDFService*        gRDFService;
     115                 :     static nsIRDFContainerUtils* gRDFContainerUtils;
     116                 :     static nsIRDFResource*       kRDF_nextVal;
     117                 : };
     118                 : 
     119                 : 
     120                 : PRInt32               RDFContainerImpl::gRefCnt = 0;
     121                 : nsIRDFService*        RDFContainerImpl::gRDFService;
     122                 : nsIRDFContainerUtils* RDFContainerImpl::gRDFContainerUtils;
     123                 : nsIRDFResource*       RDFContainerImpl::kRDF_nextVal;
     124                 : 
     125                 : ////////////////////////////////////////////////////////////////////////
     126                 : // nsISupports interface
     127                 : 
     128           14811 : NS_IMPL_ISUPPORTS1(RDFContainerImpl, nsIRDFContainer)
     129                 : 
     130                 : 
     131                 : 
     132                 : ////////////////////////////////////////////////////////////////////////
     133                 : // nsIRDFContainer interface
     134                 : 
     135                 : NS_IMETHODIMP
     136               0 : RDFContainerImpl::GetDataSource(nsIRDFDataSource** _retval)
     137                 : {
     138               0 :     *_retval = mDataSource;
     139               0 :     NS_IF_ADDREF(*_retval);
     140               0 :     return NS_OK;
     141                 : }
     142                 : 
     143                 : 
     144                 : NS_IMETHODIMP
     145              11 : RDFContainerImpl::GetResource(nsIRDFResource** _retval)
     146                 : {
     147              11 :     *_retval = mContainer;
     148              11 :     NS_IF_ADDREF(*_retval);
     149              11 :     return NS_OK;
     150                 : }
     151                 : 
     152                 : 
     153                 : NS_IMETHODIMP
     154            2288 : RDFContainerImpl::Init(nsIRDFDataSource *aDataSource, nsIRDFResource *aContainer)
     155                 : {
     156            2288 :     NS_PRECONDITION(aDataSource != nsnull, "null ptr");
     157            2288 :     if (! aDataSource)
     158               0 :         return NS_ERROR_NULL_POINTER;
     159                 : 
     160            2288 :     NS_PRECONDITION(aContainer != nsnull, "null ptr");
     161            2288 :     if (! aContainer)
     162               0 :         return NS_ERROR_NULL_POINTER;
     163                 : 
     164                 :     nsresult rv;
     165                 :     bool isContainer;
     166            2288 :     rv = gRDFContainerUtils->IsContainer(aDataSource, aContainer, &isContainer);
     167            2288 :     if (NS_FAILED(rv)) return rv;
     168                 : 
     169                 :     // ``throw'' if we can't create a container on the specified
     170                 :     // datasource/resource combination.
     171            2288 :     if (! isContainer)
     172               0 :         return NS_ERROR_FAILURE;
     173                 : 
     174            2288 :     NS_IF_RELEASE(mDataSource);
     175            2288 :     mDataSource = aDataSource;
     176            2288 :     NS_ADDREF(mDataSource);
     177                 : 
     178            2288 :     NS_IF_RELEASE(mContainer);
     179            2288 :     mContainer = aContainer;
     180            2288 :     NS_ADDREF(mContainer);
     181                 : 
     182            2288 :     return NS_OK;
     183                 : }
     184                 : 
     185                 : 
     186                 : NS_IMETHODIMP
     187               2 : RDFContainerImpl::GetCount(PRInt32 *aCount)
     188                 : {
     189               2 :     if (!mDataSource || !mContainer)
     190               0 :         return NS_ERROR_NOT_INITIALIZED;
     191                 : 
     192                 :     nsresult rv;
     193                 : 
     194                 :     // Get the next value, which hangs off of the bag via the
     195                 :     // RDF:nextVal property. This is the _next value_ that will get
     196                 :     // assigned in a one-indexed array. So, it's actually _one more_
     197                 :     // than the actual count of elements in the container.
     198                 :     //
     199                 :     // XXX To handle aggregation, this should probably be a
     200                 :     // GetTargets() that enumerates all of the values and picks the
     201                 :     // largest one.
     202               4 :     nsCOMPtr<nsIRDFNode> nextValNode;
     203               2 :     rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, true, getter_AddRefs(nextValNode));
     204               2 :     if (NS_FAILED(rv)) return rv;
     205                 : 
     206               2 :     if (rv == NS_RDF_NO_VALUE)
     207               0 :         return NS_ERROR_UNEXPECTED;
     208                 : 
     209               4 :     nsCOMPtr<nsIRDFLiteral> nextValLiteral;
     210               2 :     rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
     211               2 :     if (NS_FAILED(rv)) return rv;
     212                 : 
     213                 :     const PRUnichar *s;
     214               2 :     rv = nextValLiteral->GetValueConst( &s );
     215               2 :     if (NS_FAILED(rv)) return rv;
     216                 : 
     217               4 :     nsAutoString nextValStr(s);
     218                 : 
     219                 :     PRInt32 nextVal;
     220                 :     PRInt32 err;
     221               2 :     nextVal = nextValStr.ToInteger(&err);
     222               2 :     if (NS_FAILED(err))
     223               0 :         return NS_ERROR_UNEXPECTED;
     224                 : 
     225               2 :     *aCount = nextVal - 1;
     226               2 :     return NS_OK;
     227                 : }
     228                 : 
     229                 : 
     230                 : NS_IMETHODIMP
     231             262 : RDFContainerImpl::GetElements(nsISimpleEnumerator **_retval)
     232                 : {
     233             262 :     if (!mDataSource || !mContainer)
     234               0 :         return NS_ERROR_NOT_INITIALIZED;
     235                 : 
     236             262 :     return NS_NewContainerEnumerator(mDataSource, mContainer, _retval);
     237                 : }
     238                 : 
     239                 : 
     240                 : NS_IMETHODIMP
     241            2018 : RDFContainerImpl::AppendElement(nsIRDFNode *aElement)
     242                 : {
     243            2018 :     if (!mDataSource || !mContainer)
     244               0 :         return NS_ERROR_NOT_INITIALIZED;
     245                 : 
     246            2018 :     NS_PRECONDITION(aElement != nsnull, "null ptr");
     247            2018 :     if (! aElement)
     248               0 :         return NS_ERROR_NULL_POINTER;
     249                 : 
     250                 :     nsresult rv;
     251                 : 
     252            4036 :     nsCOMPtr<nsIRDFResource> nextVal;
     253            2018 :     rv = GetNextValue(getter_AddRefs(nextVal));
     254            2018 :     if (NS_FAILED(rv)) return rv;
     255                 : 
     256            2018 :     rv = mDataSource->Assert(mContainer, nextVal, aElement, true);
     257            2018 :     if (NS_FAILED(rv)) return rv;
     258                 : 
     259            2018 :     return NS_OK;
     260                 : }
     261                 : 
     262                 : 
     263                 : NS_IMETHODIMP
     264               0 : RDFContainerImpl::RemoveElement(nsIRDFNode *aElement, bool aRenumber)
     265                 : {
     266               0 :     if (!mDataSource || !mContainer)
     267               0 :         return NS_ERROR_NOT_INITIALIZED;
     268                 : 
     269               0 :     NS_PRECONDITION(aElement != nsnull, "null ptr");
     270               0 :     if (! aElement)
     271               0 :         return NS_ERROR_NULL_POINTER;
     272                 : 
     273                 :     nsresult rv;
     274                 : 
     275                 :     PRInt32 idx;
     276               0 :     rv = IndexOf(aElement, &idx);
     277               0 :     if (NS_FAILED(rv)) return rv;
     278                 : 
     279               0 :     if (idx < 0)
     280               0 :         return NS_OK;
     281                 : 
     282                 :     // Remove the element.
     283               0 :     nsCOMPtr<nsIRDFResource> ordinal;
     284                 :     rv = gRDFContainerUtils->IndexToOrdinalResource(idx,
     285               0 :                                                     getter_AddRefs(ordinal));
     286               0 :     if (NS_FAILED(rv)) return rv;
     287                 : 
     288               0 :     rv = mDataSource->Unassert(mContainer, ordinal, aElement);
     289               0 :     if (NS_FAILED(rv)) return rv;
     290                 : 
     291               0 :     if (aRenumber) {
     292                 :         // Now slide the rest of the collection backwards to fill in
     293                 :         // the gap. This will have the side effect of completely
     294                 :         // renumber the container from index to the end.
     295               0 :         rv = Renumber(idx + 1, -1);
     296               0 :         if (NS_FAILED(rv)) return rv;
     297                 :     }
     298                 : 
     299               0 :     return NS_OK;
     300                 : }
     301                 : 
     302                 : 
     303                 : NS_IMETHODIMP
     304               0 : RDFContainerImpl::InsertElementAt(nsIRDFNode *aElement, PRInt32 aIndex, bool aRenumber)
     305                 : {
     306               0 :     if (!mDataSource || !mContainer)
     307               0 :         return NS_ERROR_NOT_INITIALIZED;
     308                 : 
     309               0 :     NS_PRECONDITION(aElement != nsnull, "null ptr");
     310               0 :     if (! aElement)
     311               0 :         return NS_ERROR_NULL_POINTER;
     312                 : 
     313               0 :     NS_PRECONDITION(aIndex >= 1, "illegal value");
     314               0 :     if (aIndex < 1)
     315               0 :         return NS_ERROR_ILLEGAL_VALUE;
     316                 : 
     317                 :     nsresult rv;
     318                 : 
     319                 :     PRInt32 count;
     320               0 :     rv = GetCount(&count);
     321               0 :     if (NS_FAILED(rv)) return rv;
     322                 : 
     323               0 :     NS_ASSERTION(aIndex <= count + 1, "illegal value");
     324               0 :     if (aIndex > count + 1)
     325               0 :         return NS_ERROR_ILLEGAL_VALUE;
     326                 : 
     327               0 :     if (aRenumber) {
     328                 :         // Make a hole for the element. This will have the side effect of
     329                 :         // completely renumbering the container from 'aIndex' to 'count',
     330                 :         // and will spew assertions.
     331               0 :         rv = Renumber(aIndex, +1);
     332               0 :         if (NS_FAILED(rv)) return rv;
     333                 :     }
     334                 : 
     335               0 :     nsCOMPtr<nsIRDFResource> ordinal;
     336               0 :     rv = gRDFContainerUtils->IndexToOrdinalResource(aIndex, getter_AddRefs(ordinal));
     337               0 :     if (NS_FAILED(rv)) return rv;
     338                 : 
     339               0 :     rv = mDataSource->Assert(mContainer, ordinal, aElement, true);
     340               0 :     if (NS_FAILED(rv)) return rv;
     341                 : 
     342               0 :     return NS_OK;
     343                 : }
     344                 : 
     345                 : NS_IMETHODIMP
     346               1 : RDFContainerImpl::RemoveElementAt(PRInt32 aIndex, bool aRenumber, nsIRDFNode** _retval)
     347                 : {
     348               1 :     if (!mDataSource || !mContainer)
     349               0 :         return NS_ERROR_NOT_INITIALIZED;
     350                 : 
     351               1 :     *_retval = nsnull;
     352                 : 
     353               1 :     if (aIndex< 1)
     354               0 :         return NS_ERROR_ILLEGAL_VALUE;
     355                 : 
     356                 :     nsresult rv;
     357                 : 
     358                 :     PRInt32 count;
     359               1 :     rv = GetCount(&count);
     360               1 :     if (NS_FAILED(rv)) return rv;
     361                 : 
     362               1 :     if (aIndex > count)
     363               0 :         return NS_ERROR_ILLEGAL_VALUE;
     364                 : 
     365               2 :     nsCOMPtr<nsIRDFResource> ordinal;
     366               1 :     rv = gRDFContainerUtils->IndexToOrdinalResource(aIndex, getter_AddRefs(ordinal));
     367               1 :     if (NS_FAILED(rv)) return rv;
     368                 : 
     369               2 :     nsCOMPtr<nsIRDFNode> old;
     370               1 :     rv = mDataSource->GetTarget(mContainer, ordinal, true, getter_AddRefs(old));
     371               1 :     if (NS_FAILED(rv)) return rv;
     372                 : 
     373               1 :     if (rv == NS_OK) {
     374               1 :         rv = mDataSource->Unassert(mContainer, ordinal, old);
     375               1 :         if (NS_FAILED(rv)) return rv;
     376                 : 
     377               1 :         if (aRenumber) {
     378                 :             // Now slide the rest of the collection backwards to fill in
     379                 :             // the gap. This will have the side effect of completely
     380                 :             // renumber the container from index to the end.
     381               1 :             rv = Renumber(aIndex + 1, -1);
     382               1 :             if (NS_FAILED(rv)) return rv;
     383                 :         }
     384                 :     }
     385                 : 
     386               1 :     old.swap(*_retval);
     387                 : 
     388               1 :     return NS_OK;
     389                 : }
     390                 : 
     391                 : NS_IMETHODIMP
     392              19 : RDFContainerImpl::IndexOf(nsIRDFNode *aElement, PRInt32 *aIndex)
     393                 : {
     394              19 :     if (!mDataSource || !mContainer)
     395               0 :         return NS_ERROR_NOT_INITIALIZED;
     396                 : 
     397                 :     return gRDFContainerUtils->IndexOf(mDataSource, mContainer,
     398              19 :                                        aElement, aIndex);
     399                 : }
     400                 : 
     401                 : 
     402                 : ////////////////////////////////////////////////////////////////////////
     403                 : 
     404                 : 
     405            2288 : RDFContainerImpl::RDFContainerImpl()
     406            2288 :     : mDataSource(nsnull), mContainer(nsnull)
     407                 : {
     408            2288 : }
     409                 : 
     410                 : 
     411                 : nsresult
     412            2288 : RDFContainerImpl::Init()
     413                 : {
     414            2288 :     if (gRefCnt++ == 0) {
     415                 :         nsresult rv;
     416                 : 
     417            2252 :         rv = CallGetService(kRDFServiceCID, &gRDFService);
     418            2252 :         if (NS_FAILED(rv)) {
     419               0 :             NS_ERROR("unable to get RDF service");
     420               0 :             return rv;
     421                 :         }
     422                 : 
     423            2252 :         rv = gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
     424            2252 :                                       &kRDF_nextVal);
     425            2252 :         if (NS_FAILED(rv)) return rv;
     426                 : 
     427            2252 :         rv = CallGetService(kRDFContainerUtilsCID, &gRDFContainerUtils);
     428            2252 :         if (NS_FAILED(rv)) {
     429               0 :             NS_ERROR("unable to get RDF container utils service");
     430               0 :             return rv;
     431                 :         }
     432                 :     }
     433                 : 
     434            2288 :     return NS_OK;
     435                 : }
     436                 : 
     437                 : 
     438            4576 : RDFContainerImpl::~RDFContainerImpl()
     439                 : {
     440                 : #ifdef DEBUG_REFS
     441                 :     --gInstanceCount;
     442                 :     fprintf(stdout, "%d - RDF: RDFContainerImpl\n", gInstanceCount);
     443                 : #endif
     444                 : 
     445            2288 :     NS_IF_RELEASE(mContainer);
     446            2288 :     NS_IF_RELEASE(mDataSource);
     447                 : 
     448            2288 :     if (--gRefCnt == 0) {
     449            2252 :         NS_IF_RELEASE(gRDFContainerUtils);
     450            2252 :         NS_IF_RELEASE(gRDFService);
     451            2252 :         NS_IF_RELEASE(kRDF_nextVal);
     452                 :     }
     453            9152 : }
     454                 : 
     455                 : 
     456                 : nsresult
     457            2288 : NS_NewRDFContainer(nsIRDFContainer** aResult)
     458                 : {
     459            2288 :     RDFContainerImpl* result = new RDFContainerImpl();
     460            2288 :     if (! result)
     461               0 :         return NS_ERROR_OUT_OF_MEMORY;
     462                 : 
     463                 :     nsresult rv;
     464            2288 :     rv = result->Init();
     465            2288 :     if (NS_FAILED(rv)) {
     466               0 :         delete result;
     467               0 :         return rv;
     468                 :     }
     469                 : 
     470            2288 :     NS_ADDREF(result);
     471            2288 :     *aResult = result;
     472            2288 :     return NS_OK;
     473                 : }
     474                 : 
     475                 : 
     476                 : nsresult
     477               0 : NS_NewRDFContainer(nsIRDFDataSource* aDataSource,
     478                 :                    nsIRDFResource* aResource,
     479                 :                    nsIRDFContainer** aResult)
     480                 : {
     481                 :     nsresult rv;
     482               0 :     rv = NS_NewRDFContainer(aResult);
     483               0 :     if (NS_FAILED(rv)) return rv;
     484                 : 
     485               0 :     rv = (*aResult)->Init(aDataSource, aResource);
     486               0 :     if (NS_FAILED(rv)) {
     487               0 :         NS_RELEASE(*aResult);
     488                 :     }
     489               0 :     return rv;
     490                 : }
     491                 : 
     492                 : 
     493                 : nsresult
     494               1 : RDFContainerImpl::Renumber(PRInt32 aStartIndex, PRInt32 aIncrement)
     495                 : {
     496               1 :     if (!mDataSource || !mContainer)
     497               0 :         return NS_ERROR_NOT_INITIALIZED;
     498                 : 
     499                 :     // Renumber the elements in the container starting with
     500                 :     // aStartIndex, updating each element's index by aIncrement. For
     501                 :     // example,
     502                 :     //
     503                 :     //   (1:a 2:b 3:c)
     504                 :     //   Renumber(2, +1);
     505                 :     //   (1:a 3:b 4:c)
     506                 :     //   Renumber(3, -1);
     507                 :     //   (1:a 2:b 3:c)
     508                 :     //
     509                 :     nsresult rv;
     510                 : 
     511               1 :     if (! aIncrement)
     512               0 :         return NS_OK;
     513                 : 
     514                 :     PRInt32 count;
     515               1 :     rv = GetCount(&count);
     516               1 :     if (NS_FAILED(rv)) return rv;
     517                 : 
     518               1 :     if (aIncrement > 0) {
     519                 :         // Update the container's nextVal to reflect the
     520                 :         // renumbering. We do this now if aIncrement > 0 because we'll
     521                 :         // want to be able to acknowledge that new elements are in the
     522                 :         // container.
     523               0 :         rv = SetNextValue(count + aIncrement + 1);
     524               0 :         if (NS_FAILED(rv)) return rv;
     525                 :     }
     526                 : 
     527                 :     PRInt32 i;
     528               1 :     if (aIncrement < 0) {
     529               1 :         i = aStartIndex;
     530                 :     }
     531                 :     else {
     532               0 :         i = count; // we're one-indexed.
     533                 :     }
     534                 : 
     535                 :     // Note: once we disable notifications, don't exit this method until
     536                 :     // enabling notifications
     537                 :     nsCOMPtr<nsIRDFPropagatableDataSource> propagatable =
     538               2 :         do_QueryInterface(mDataSource);
     539               1 :     if (propagatable) {
     540               0 :         propagatable->SetPropagateChanges(false);
     541                 :     }
     542                 : 
     543               1 :     bool    err = false;
     544               2 :     while (!err && ((aIncrement < 0) ? (i <= count) : (i >= aStartIndex)))
     545                 :     {
     546               0 :         nsCOMPtr<nsIRDFResource> oldOrdinal;
     547               0 :         rv = gRDFContainerUtils->IndexToOrdinalResource(i, getter_AddRefs(oldOrdinal));
     548               0 :         if (NS_FAILED(rv))
     549                 :         {
     550               0 :             err = true;
     551               0 :             continue;
     552                 :         }
     553                 : 
     554               0 :         nsCOMPtr<nsIRDFResource> newOrdinal;
     555               0 :         rv = gRDFContainerUtils->IndexToOrdinalResource(i + aIncrement, getter_AddRefs(newOrdinal));
     556               0 :         if (NS_FAILED(rv))
     557                 :         {
     558               0 :             err = true;
     559               0 :             continue;
     560                 :         }
     561                 : 
     562                 :         // Because of aggregation, we need to be paranoid about the
     563                 :         // possibility that >1 element may be present per ordinal. If
     564                 :         // there _is_ in fact more than one element, they'll all get
     565                 :         // assigned to the same new ordinal; i.e., we don't make any
     566                 :         // attempt to "clean up" the duplicate numbering. (Doing so
     567                 :         // would require two passes.)
     568               0 :         nsCOMPtr<nsISimpleEnumerator> targets;
     569               0 :         rv = mDataSource->GetTargets(mContainer, oldOrdinal, true, getter_AddRefs(targets));
     570               0 :         if (NS_FAILED(rv))
     571                 :         {
     572               0 :             err = true;
     573               0 :             continue;
     574                 :         }
     575                 : 
     576               0 :         while (1) {
     577                 :             bool hasMore;
     578               0 :             rv = targets->HasMoreElements(&hasMore);
     579               0 :             if (NS_FAILED(rv))
     580                 :             {
     581               0 :                 err = true;
     582               0 :                 break;
     583                 :             }
     584                 : 
     585               0 :             if (! hasMore)
     586               0 :                 break;
     587                 : 
     588               0 :             nsCOMPtr<nsISupports> isupports;
     589               0 :             rv = targets->GetNext(getter_AddRefs(isupports));
     590               0 :             if (NS_FAILED(rv))
     591                 :             {
     592               0 :                 err = true;
     593                 :                 break;
     594                 :             }
     595                 : 
     596               0 :             nsCOMPtr<nsIRDFNode> element( do_QueryInterface(isupports) );
     597               0 :             NS_ASSERTION(element != nsnull, "something funky in the enumerator");
     598               0 :             if (! element)
     599                 :             {
     600               0 :                 err = true;
     601               0 :                 rv = NS_ERROR_UNEXPECTED;
     602                 :                 break;
     603                 :             }
     604                 : 
     605               0 :             rv = mDataSource->Unassert(mContainer, oldOrdinal, element);
     606               0 :             if (NS_FAILED(rv))
     607                 :             {
     608               0 :                 err = true;
     609                 :                 break;
     610                 :             }
     611                 : 
     612               0 :             rv = mDataSource->Assert(mContainer, newOrdinal, element, true);
     613               0 :             if (NS_FAILED(rv))
     614                 :             {
     615               0 :                 err = true;
     616                 :                 break;
     617                 :             }
     618                 :         }
     619                 : 
     620               0 :         i -= aIncrement;
     621                 :     }
     622                 : 
     623               1 :     if (!err && (aIncrement < 0))
     624                 :     {
     625                 :         // Update the container's nextVal to reflect the
     626                 :         // renumbering. We do this now if aIncrement < 0 because, up
     627                 :         // until this point, we'll want people to be able to find
     628                 :         // things that are still "at the end".
     629               1 :         rv = SetNextValue(count + aIncrement + 1);
     630               1 :         if (NS_FAILED(rv))
     631                 :         {
     632               0 :             err = true;
     633                 :         }
     634                 :     }
     635                 : 
     636                 :     // Note: MUST enable notifications before exiting this method
     637               1 :     if (propagatable) {
     638               0 :         propagatable->SetPropagateChanges(true);
     639                 :     }
     640                 : 
     641               1 :     if (err) return(rv);
     642                 : 
     643               1 :     return NS_OK;
     644                 : }
     645                 : 
     646                 : 
     647                 : 
     648                 : nsresult
     649               1 : RDFContainerImpl::SetNextValue(PRInt32 aIndex)
     650                 : {
     651               1 :     if (!mDataSource || !mContainer)
     652               0 :         return NS_ERROR_NOT_INITIALIZED;
     653                 : 
     654                 :     nsresult rv;
     655                 : 
     656                 :     // Remove the current value of nextVal, if there is one.
     657               2 :     nsCOMPtr<nsIRDFNode> nextValNode;
     658               1 :     if (NS_SUCCEEDED(rv = mDataSource->GetTarget(mContainer,
     659                 :                                                  kRDF_nextVal,
     660                 :                                                  true,
     661                 :                                                  getter_AddRefs(nextValNode)))) {
     662               1 :         if (NS_FAILED(rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValNode))) {
     663               0 :             NS_ERROR("unable to update nextVal");
     664               0 :             return rv;
     665                 :         }
     666                 :     }
     667                 : 
     668               2 :     nsAutoString s;
     669               1 :     s.AppendInt(aIndex, 10);
     670                 : 
     671               2 :     nsCOMPtr<nsIRDFLiteral> nextVal;
     672               1 :     if (NS_FAILED(rv = gRDFService->GetLiteral(s.get(), getter_AddRefs(nextVal)))) {
     673               0 :         NS_ERROR("unable to get nextVal literal");
     674               0 :         return rv;
     675                 :     }
     676                 : 
     677               1 :     rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextVal, true);
     678               1 :     if (rv != NS_RDF_ASSERTION_ACCEPTED) {
     679               0 :         NS_ERROR("unable to update nextVal");
     680               0 :         return NS_ERROR_FAILURE;
     681                 :     }
     682                 : 
     683               1 :     return NS_OK;
     684                 : }
     685                 : 
     686                 : 
     687                 : nsresult
     688            2018 : RDFContainerImpl::GetNextValue(nsIRDFResource** aResult)
     689                 : {
     690            2018 :     if (!mDataSource || !mContainer)
     691               0 :         return NS_ERROR_NOT_INITIALIZED;
     692                 : 
     693                 :     nsresult rv;
     694                 : 
     695                 :     // Get the next value, which hangs off of the bag via the
     696                 :     // RDF:nextVal property.
     697            4036 :     nsCOMPtr<nsIRDFNode> nextValNode;
     698            2018 :     rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, true, getter_AddRefs(nextValNode));
     699            2018 :     if (NS_FAILED(rv)) return rv;
     700                 : 
     701            2018 :     if (rv == NS_RDF_NO_VALUE)
     702               0 :         return NS_ERROR_UNEXPECTED;
     703                 : 
     704            4036 :     nsCOMPtr<nsIRDFLiteral> nextValLiteral;
     705            2018 :     rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
     706            2018 :     if (NS_FAILED(rv)) return rv;
     707                 : 
     708                 :     const PRUnichar* s;
     709            2018 :     rv = nextValLiteral->GetValueConst(&s);
     710            2018 :     if (NS_FAILED(rv)) return rv;
     711                 : 
     712            2018 :     PRInt32 nextVal = 0;
     713                 :     {
     714            4036 :         for (const PRUnichar* p = s; *p != 0; ++p) {
     715            2018 :             NS_ASSERTION(*p >= '0' && *p <= '9', "not a digit");
     716            2018 :             if (*p < '0' || *p > '9')
     717               0 :                 break;
     718                 : 
     719            2018 :             nextVal *= 10;
     720            2018 :             nextVal += *p - '0';
     721                 :         }
     722                 :     }
     723                 : 
     724                 :     char buf[sizeof(kRDFNameSpaceURI) + 16];
     725            4036 :     nsFixedCString nextValStr(buf, sizeof(buf), 0);
     726            2018 :     nextValStr = kRDFNameSpaceURI;
     727            2018 :     nextValStr.Append("_");
     728            2018 :     nextValStr.AppendInt(nextVal, 10);
     729                 : 
     730            2018 :     rv = gRDFService->GetResource(nextValStr, aResult);
     731            2018 :     if (NS_FAILED(rv)) return rv;
     732                 : 
     733                 :     // Now increment the RDF:nextVal property.
     734            2018 :     rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValLiteral);
     735            2018 :     if (NS_FAILED(rv)) return rv;
     736                 : 
     737            2018 :     ++nextVal;
     738            2018 :     nextValStr.Truncate();
     739            2018 :     nextValStr.AppendInt(nextVal, 10);
     740                 : 
     741            2018 :     rv = gRDFService->GetLiteral(NS_ConvertASCIItoUTF16(nextValStr).get(), getter_AddRefs(nextValLiteral));
     742            2018 :     if (NS_FAILED(rv)) return rv;
     743                 : 
     744            2018 :     rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextValLiteral, true);
     745            2018 :     if (NS_FAILED(rv)) return rv;
     746                 : 
     747            2018 :     if (RDF_SEQ_LIST_LIMIT == nextVal)
     748                 :     {
     749                 :         // focal point for RDF container mutation;
     750                 :         // basically, provide a hint to allow for fast access
     751               8 :         nsCOMPtr<nsIRDFInMemoryDataSource> inMem = do_QueryInterface(mDataSource);
     752               4 :         if (inMem)
     753                 :         {
     754                 :             // ignore error; failure just means slower access
     755               0 :             (void)inMem->EnsureFastContainment(mContainer);
     756                 :         }
     757                 :     }
     758                 : 
     759            2018 :     return NS_OK;
     760                 : }

Generated by: LCOV version 1.7