rdf/base/src/nsRDFContainerUtils.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     8   Implementation for the RDF container utils.
    10  */
    13 #include "nsCOMPtr.h"
    14 #include "nsIServiceManager.h"
    15 #include "nsIRDFContainer.h"
    16 #include "nsIRDFContainerUtils.h"
    17 #include "nsIRDFService.h"
    18 #include "nsRDFCID.h"
    19 #include "nsString.h"
    20 #include "nsXPIDLString.h"
    21 #include "plstr.h"
    22 #include "prprf.h"
    23 #include "rdf.h"
    24 #include "rdfutil.h"
    26 class RDFContainerUtilsImpl : public nsIRDFContainerUtils
    27 {
    28 public:
    29     // nsISupports interface
    30     NS_DECL_ISUPPORTS
    32     // nsIRDFContainerUtils interface
    33     NS_DECL_NSIRDFCONTAINERUTILS
    35 private:
    36     friend nsresult NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult);
    38     RDFContainerUtilsImpl();
    39     virtual ~RDFContainerUtilsImpl();
    41     nsresult MakeContainer(nsIRDFDataSource* aDataSource,
    42                            nsIRDFResource* aResource,
    43                            nsIRDFResource* aType,
    44                            nsIRDFContainer** aResult);
    46     bool IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
    48     // pseudo constants
    49     static int32_t gRefCnt;
    50     static nsIRDFService* gRDFService;
    51     static nsIRDFResource* kRDF_instanceOf;
    52     static nsIRDFResource* kRDF_nextVal;
    53     static nsIRDFResource* kRDF_Bag;
    54     static nsIRDFResource* kRDF_Seq;
    55     static nsIRDFResource* kRDF_Alt;
    56     static nsIRDFLiteral* kOne;
    57     static const char kRDFNameSpaceURI[];
    58 };
    60 int32_t         RDFContainerUtilsImpl::gRefCnt = 0;
    61 nsIRDFService*  RDFContainerUtilsImpl::gRDFService;
    62 nsIRDFResource* RDFContainerUtilsImpl::kRDF_instanceOf;
    63 nsIRDFResource* RDFContainerUtilsImpl::kRDF_nextVal;
    64 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Bag;
    65 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Seq;
    66 nsIRDFResource* RDFContainerUtilsImpl::kRDF_Alt;
    67 nsIRDFLiteral*  RDFContainerUtilsImpl::kOne;
    68 const char      RDFContainerUtilsImpl::kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
    70 ////////////////////////////////////////////////////////////////////////
    71 // nsISupports interface
    73 NS_IMPL_ISUPPORTS(RDFContainerUtilsImpl, nsIRDFContainerUtils)
    75 ////////////////////////////////////////////////////////////////////////
    76 // nsIRDFContainerUtils interface
    78 NS_IMETHODIMP
    79 RDFContainerUtilsImpl::IsOrdinalProperty(nsIRDFResource *aProperty, bool *_retval)
    80 {
    81     NS_PRECONDITION(aProperty != nullptr, "null ptr");
    82     if (! aProperty)
    83         return NS_ERROR_NULL_POINTER;
    85     nsresult rv;
    87     const char	*propertyStr;
    88     rv = aProperty->GetValueConst( &propertyStr );
    89     if (NS_FAILED(rv)) return rv;
    91     if (PL_strncmp(propertyStr, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
    92         *_retval = false;
    93         return NS_OK;
    94     }
    96     const char* s = propertyStr;
    97     s += sizeof(kRDFNameSpaceURI) - 1;
    98     if (*s != '_') {
    99         *_retval = false;
   100         return NS_OK;
   101     }
   103     ++s;
   104     while (*s) {
   105         if (*s < '0' || *s > '9') {
   106             *_retval = false;
   107             return NS_OK;
   108         }
   110         ++s;
   111     }
   113     *_retval = true;
   114     return NS_OK;
   115 }
   118 NS_IMETHODIMP
   119 RDFContainerUtilsImpl::IndexToOrdinalResource(int32_t aIndex, nsIRDFResource **aOrdinal)
   120 {
   121     NS_PRECONDITION(aIndex > 0, "illegal value");
   122     if (aIndex <= 0)
   123         return NS_ERROR_ILLEGAL_VALUE;
   125     nsAutoCString uri(kRDFNameSpaceURI);
   126     uri.Append('_');
   127     uri.AppendInt(aIndex);
   129     nsresult rv = gRDFService->GetResource(uri, aOrdinal);
   130     NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get ordinal resource");
   131     if (NS_FAILED(rv)) return rv;
   133     return NS_OK;
   134 }
   137 NS_IMETHODIMP
   138 RDFContainerUtilsImpl::OrdinalResourceToIndex(nsIRDFResource *aOrdinal, int32_t *aIndex)
   139 {
   140     NS_PRECONDITION(aOrdinal != nullptr, "null ptr");
   141     if (! aOrdinal)
   142         return NS_ERROR_NULL_POINTER;
   144     const char	*ordinalStr;
   145     if (NS_FAILED(aOrdinal->GetValueConst( &ordinalStr )))
   146         return NS_ERROR_FAILURE;
   148     const char* s = ordinalStr;
   149     if (PL_strncmp(s, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
   150         NS_ERROR("not an ordinal");
   151         return NS_ERROR_UNEXPECTED;
   152     }
   154     s += sizeof(kRDFNameSpaceURI) - 1;
   155     if (*s != '_') {
   156         NS_ERROR("not an ordinal");
   157         return NS_ERROR_UNEXPECTED;
   158     }
   160     int32_t idx = 0;
   162     ++s;
   163     while (*s) {
   164         if (*s < '0' || *s > '9') {
   165             NS_ERROR("not an ordinal");
   166             return NS_ERROR_UNEXPECTED;
   167         }
   169         idx *= 10;
   170         idx += (*s - '0');
   172         ++s;
   173     }
   175     *aIndex = idx;
   176     return NS_OK;
   177 }
   179 NS_IMETHODIMP
   180 RDFContainerUtilsImpl::IsContainer(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
   181 {
   182     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
   183     if (! aDataSource)
   184         return NS_ERROR_NULL_POINTER;
   186     NS_PRECONDITION(aResource != nullptr, "null ptr");
   187     if (! aResource)
   188         return NS_ERROR_NULL_POINTER;
   190     NS_PRECONDITION(_retval != nullptr, "null ptr");
   191     if (! _retval)
   192         return NS_ERROR_NULL_POINTER;
   194     if (IsA(aDataSource, aResource, kRDF_Seq) ||
   195         IsA(aDataSource, aResource, kRDF_Bag) ||
   196         IsA(aDataSource, aResource, kRDF_Alt)) {
   197         *_retval = true;
   198     }
   199     else {
   200         *_retval = false;
   201     }
   202     return NS_OK;
   203 }
   206 NS_IMETHODIMP
   207 RDFContainerUtilsImpl::IsEmpty(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, bool* _retval)
   208 {
   209     if (! aDataSource)
   210         return NS_ERROR_NULL_POINTER;
   212     nsresult rv;
   214     // By default, say that we're an empty container. Even if we're not
   215     // really even a container.
   216     *_retval = true;
   218     nsCOMPtr<nsIRDFNode> nextValNode;
   219     rv = aDataSource->GetTarget(aResource, kRDF_nextVal, true, getter_AddRefs(nextValNode));
   220     if (NS_FAILED(rv)) return rv;
   222     if (rv == NS_RDF_NO_VALUE)
   223         return NS_OK;
   225     nsCOMPtr<nsIRDFLiteral> nextValLiteral;
   226     rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
   227     if (NS_FAILED(rv)) return rv;
   229     if (nextValLiteral.get() != kOne)
   230         *_retval = false;
   232     return NS_OK;
   233 }
   236 NS_IMETHODIMP
   237 RDFContainerUtilsImpl::IsBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
   238 {
   239     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
   240     if (! aDataSource)
   241         return NS_ERROR_NULL_POINTER;
   243     NS_PRECONDITION(aResource != nullptr, "null ptr");
   244     if (! aResource)
   245         return NS_ERROR_NULL_POINTER;
   247     NS_PRECONDITION(_retval != nullptr, "null ptr");
   248     if (! _retval)
   249         return NS_ERROR_NULL_POINTER;
   251     *_retval = IsA(aDataSource, aResource, kRDF_Bag);
   252     return NS_OK;
   253 }
   256 NS_IMETHODIMP
   257 RDFContainerUtilsImpl::IsSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
   258 {
   259     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
   260     if (! aDataSource)
   261         return NS_ERROR_NULL_POINTER;
   263     NS_PRECONDITION(aResource != nullptr, "null ptr");
   264     if (! aResource)
   265         return NS_ERROR_NULL_POINTER;
   267     NS_PRECONDITION(_retval != nullptr, "null ptr");
   268     if (! _retval)
   269         return NS_ERROR_NULL_POINTER;
   271     *_retval = IsA(aDataSource, aResource, kRDF_Seq);
   272     return NS_OK;
   273 }
   276 NS_IMETHODIMP
   277 RDFContainerUtilsImpl::IsAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
   278 {
   279     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
   280     if (! aDataSource)
   281         return NS_ERROR_NULL_POINTER;
   283     NS_PRECONDITION(aResource != nullptr, "null ptr");
   284     if (! aResource)
   285         return NS_ERROR_NULL_POINTER;
   287     NS_PRECONDITION(_retval != nullptr, "null ptr");
   288     if (! _retval)
   289         return NS_ERROR_NULL_POINTER;
   291     *_retval = IsA(aDataSource, aResource, kRDF_Alt);
   292     return NS_OK;
   293 }
   296 NS_IMETHODIMP
   297 RDFContainerUtilsImpl::MakeBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
   298 {
   299     return MakeContainer(aDataSource, aResource, kRDF_Bag, _retval);
   300 }
   303 NS_IMETHODIMP
   304 RDFContainerUtilsImpl::MakeSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
   305 {
   306     return MakeContainer(aDataSource, aResource, kRDF_Seq, _retval);
   307 }
   310 NS_IMETHODIMP
   311 RDFContainerUtilsImpl::MakeAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
   312 {
   313     return MakeContainer(aDataSource, aResource, kRDF_Alt, _retval);
   314 }
   318 ////////////////////////////////////////////////////////////////////////
   321 RDFContainerUtilsImpl::RDFContainerUtilsImpl()
   322 {
   323     if (gRefCnt++ == 0) {
   324         nsresult rv;
   326         NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
   327         rv = CallGetService(kRDFServiceCID, &gRDFService);
   329         NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
   330         if (NS_SUCCEEDED(rv)) {
   331             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
   332                                      &kRDF_instanceOf);
   333             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
   334                                      &kRDF_nextVal);
   335             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"),
   336                                      &kRDF_Bag);
   337             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"),
   338                                      &kRDF_Seq);
   339             gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"),
   340                                      &kRDF_Alt);
   341             gRDFService->GetLiteral(MOZ_UTF16("1"), &kOne);
   342         }
   343     }
   344 }
   347 RDFContainerUtilsImpl::~RDFContainerUtilsImpl()
   348 {
   349 #ifdef DEBUG_REFS
   350     --gInstanceCount;
   351     fprintf(stdout, "%d - RDF: RDFContainerUtilsImpl\n", gInstanceCount);
   352 #endif
   354     if (--gRefCnt == 0) {
   355         NS_IF_RELEASE(gRDFService);
   356         NS_IF_RELEASE(kRDF_instanceOf);
   357         NS_IF_RELEASE(kRDF_nextVal);
   358         NS_IF_RELEASE(kRDF_Bag);
   359         NS_IF_RELEASE(kRDF_Seq);
   360         NS_IF_RELEASE(kRDF_Alt);
   361         NS_IF_RELEASE(kOne);
   362     }
   363 }
   367 nsresult
   368 NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult)
   369 {
   370     NS_PRECONDITION(aResult != nullptr, "null ptr");
   371     if (! aResult)
   372         return NS_ERROR_NULL_POINTER;
   374     RDFContainerUtilsImpl* result =
   375         new RDFContainerUtilsImpl();
   377     if (! result)
   378         return NS_ERROR_OUT_OF_MEMORY;
   380     NS_ADDREF(result);
   381     *aResult = result;
   382     return NS_OK;
   383 }
   386 nsresult
   387 RDFContainerUtilsImpl::MakeContainer(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType, nsIRDFContainer** aResult)
   388 {
   389     NS_PRECONDITION(aDataSource != nullptr, "null ptr");
   390     if (! aDataSource)	return NS_ERROR_NULL_POINTER;
   392     NS_PRECONDITION(aResource != nullptr, "null ptr");
   393     if (! aResource)	return NS_ERROR_NULL_POINTER;
   395     NS_PRECONDITION(aType != nullptr, "null ptr");
   396     if (! aType)	return NS_ERROR_NULL_POINTER;
   398     if (aResult)	*aResult = nullptr;
   400     nsresult rv;
   402     // Check to see if somebody has already turned it into a container; if so
   403     // don't try to do it again.
   404     bool isContainer;
   405     rv = IsContainer(aDataSource, aResource, &isContainer);
   406     if (NS_FAILED(rv)) return rv;
   408     if (!isContainer)
   409     {
   410 	rv = aDataSource->Assert(aResource, kRDF_instanceOf, aType, true);
   411 	if (NS_FAILED(rv)) return rv;
   413 	rv = aDataSource->Assert(aResource, kRDF_nextVal, kOne, true);
   414 	if (NS_FAILED(rv)) return rv;
   415     }
   417     if (aResult) {
   418         rv = NS_NewRDFContainer(aResult);
   419         if (NS_FAILED(rv)) return rv;
   421         rv = (*aResult)->Init(aDataSource, aResource);
   422         if (NS_FAILED(rv)) return rv;
   423     }
   425     return NS_OK;
   426 }
   428 bool
   429 RDFContainerUtilsImpl::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
   430 {
   431     if (!aDataSource || !aResource || !aType) {
   432         NS_WARNING("Unexpected null argument");
   433         return false;
   434     }
   436     nsresult rv;
   438     bool result;
   439     rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, true, &result);
   440     if (NS_FAILED(rv))
   441       return false;
   443     return result;
   444 }
   446 NS_IMETHODIMP
   447 RDFContainerUtilsImpl::IndexOf(nsIRDFDataSource* aDataSource, nsIRDFResource* aContainer, nsIRDFNode* aElement, int32_t* aIndex)
   448 {
   449     if (!aDataSource || !aContainer)
   450         return NS_ERROR_NULL_POINTER;
   452     // Assume we can't find it.
   453     *aIndex = -1;
   455     // If the resource is null, bail quietly
   456     if (! aElement)
   457       return NS_OK;
   459     // We'll assume that fan-out is much higher than fan-in, so grovel
   460     // through the inbound arcs, look for an ordinal resource, and
   461     // decode it.
   462     nsCOMPtr<nsISimpleEnumerator> arcsIn;
   463     aDataSource->ArcLabelsIn(aElement, getter_AddRefs(arcsIn));
   464     if (! arcsIn)
   465         return NS_OK;
   467     while (1) {
   468         bool hasMoreArcs = false;
   469         arcsIn->HasMoreElements(&hasMoreArcs);
   470         if (! hasMoreArcs)
   471             break;
   473         nsCOMPtr<nsISupports> isupports;
   474         arcsIn->GetNext(getter_AddRefs(isupports));
   475         if (! isupports)
   476             break;
   478         nsCOMPtr<nsIRDFResource> property =
   479             do_QueryInterface(isupports);
   481         if (! property)
   482             continue;
   484         bool isOrdinal;
   485         IsOrdinalProperty(property, &isOrdinal);
   486         if (! isOrdinal)
   487             continue;
   489         nsCOMPtr<nsISimpleEnumerator> sources;
   490         aDataSource->GetSources(property, aElement, true, getter_AddRefs(sources));
   491         if (! sources)
   492             continue;
   494         while (1) {
   495             bool hasMoreSources = false;
   496             sources->HasMoreElements(&hasMoreSources);
   497             if (! hasMoreSources)
   498                 break;
   500             nsCOMPtr<nsISupports> isupports2;
   501             sources->GetNext(getter_AddRefs(isupports2));
   502             if (! isupports2)
   503                 break;
   505             nsCOMPtr<nsIRDFResource> source =
   506                 do_QueryInterface(isupports2);
   508             if (source == aContainer)
   509                 // Found it.
   510                 return OrdinalResourceToIndex(property, aIndex);
   511         }
   512     }
   514     return NS_OK;
   515 }

mercurial