summaryrefslogtreecommitdiffstats
path: root/rdf/base/nsRDFContainerUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'rdf/base/nsRDFContainerUtils.cpp')
-rw-r--r--rdf/base/nsRDFContainerUtils.cpp515
1 files changed, 515 insertions, 0 deletions
diff --git a/rdf/base/nsRDFContainerUtils.cpp b/rdf/base/nsRDFContainerUtils.cpp
new file mode 100644
index 000000000..299722d4b
--- /dev/null
+++ b/rdf/base/nsRDFContainerUtils.cpp
@@ -0,0 +1,515 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+
+ Implementation for the RDF container utils.
+
+ */
+
+
+#include "nsCOMPtr.h"
+#include "nsIServiceManager.h"
+#include "nsIRDFContainer.h"
+#include "nsIRDFContainerUtils.h"
+#include "nsIRDFService.h"
+#include "nsRDFCID.h"
+#include "nsString.h"
+#include "nsXPIDLString.h"
+#include "plstr.h"
+#include "prprf.h"
+#include "rdf.h"
+#include "rdfutil.h"
+
+class RDFContainerUtilsImpl : public nsIRDFContainerUtils
+{
+public:
+ // nsISupports interface
+ NS_DECL_ISUPPORTS
+
+ // nsIRDFContainerUtils interface
+ NS_DECL_NSIRDFCONTAINERUTILS
+
+private:
+ friend nsresult NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult);
+
+ RDFContainerUtilsImpl();
+ virtual ~RDFContainerUtilsImpl();
+
+ nsresult MakeContainer(nsIRDFDataSource* aDataSource,
+ nsIRDFResource* aResource,
+ nsIRDFResource* aType,
+ nsIRDFContainer** aResult);
+
+ bool IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType);
+
+ // pseudo constants
+ static int32_t gRefCnt;
+ static nsIRDFService* gRDFService;
+ static nsIRDFResource* kRDF_instanceOf;
+ static nsIRDFResource* kRDF_nextVal;
+ static nsIRDFResource* kRDF_Bag;
+ static nsIRDFResource* kRDF_Seq;
+ static nsIRDFResource* kRDF_Alt;
+ static nsIRDFLiteral* kOne;
+ static const char kRDFNameSpaceURI[];
+};
+
+int32_t RDFContainerUtilsImpl::gRefCnt = 0;
+nsIRDFService* RDFContainerUtilsImpl::gRDFService;
+nsIRDFResource* RDFContainerUtilsImpl::kRDF_instanceOf;
+nsIRDFResource* RDFContainerUtilsImpl::kRDF_nextVal;
+nsIRDFResource* RDFContainerUtilsImpl::kRDF_Bag;
+nsIRDFResource* RDFContainerUtilsImpl::kRDF_Seq;
+nsIRDFResource* RDFContainerUtilsImpl::kRDF_Alt;
+nsIRDFLiteral* RDFContainerUtilsImpl::kOne;
+const char RDFContainerUtilsImpl::kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
+
+////////////////////////////////////////////////////////////////////////
+// nsISupports interface
+
+NS_IMPL_ISUPPORTS(RDFContainerUtilsImpl, nsIRDFContainerUtils)
+
+////////////////////////////////////////////////////////////////////////
+// nsIRDFContainerUtils interface
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsOrdinalProperty(nsIRDFResource *aProperty, bool *_retval)
+{
+ NS_PRECONDITION(aProperty != nullptr, "null ptr");
+ if (! aProperty)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+
+ const char *propertyStr;
+ rv = aProperty->GetValueConst( &propertyStr );
+ if (NS_FAILED(rv)) return rv;
+
+ if (PL_strncmp(propertyStr, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
+ *_retval = false;
+ return NS_OK;
+ }
+
+ const char* s = propertyStr;
+ s += sizeof(kRDFNameSpaceURI) - 1;
+ if (*s != '_') {
+ *_retval = false;
+ return NS_OK;
+ }
+
+ ++s;
+ while (*s) {
+ if (*s < '0' || *s > '9') {
+ *_retval = false;
+ return NS_OK;
+ }
+
+ ++s;
+ }
+
+ *_retval = true;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IndexToOrdinalResource(int32_t aIndex, nsIRDFResource **aOrdinal)
+{
+ NS_PRECONDITION(aIndex > 0, "illegal value");
+ if (aIndex <= 0)
+ return NS_ERROR_ILLEGAL_VALUE;
+
+ nsAutoCString uri(kRDFNameSpaceURI);
+ uri.Append('_');
+ uri.AppendInt(aIndex);
+
+ nsresult rv = gRDFService->GetResource(uri, aOrdinal);
+ NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get ordinal resource");
+ if (NS_FAILED(rv)) return rv;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::OrdinalResourceToIndex(nsIRDFResource *aOrdinal, int32_t *aIndex)
+{
+ NS_PRECONDITION(aOrdinal != nullptr, "null ptr");
+ if (! aOrdinal)
+ return NS_ERROR_NULL_POINTER;
+
+ const char *ordinalStr;
+ if (NS_FAILED(aOrdinal->GetValueConst( &ordinalStr )))
+ return NS_ERROR_FAILURE;
+
+ const char* s = ordinalStr;
+ if (PL_strncmp(s, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
+ NS_ERROR("not an ordinal");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ s += sizeof(kRDFNameSpaceURI) - 1;
+ if (*s != '_') {
+ NS_ERROR("not an ordinal");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ int32_t idx = 0;
+
+ ++s;
+ while (*s) {
+ if (*s < '0' || *s > '9') {
+ NS_ERROR("not an ordinal");
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ idx *= 10;
+ idx += (*s - '0');
+
+ ++s;
+ }
+
+ *aIndex = idx;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsContainer(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
+{
+ NS_PRECONDITION(aDataSource != nullptr, "null ptr");
+ if (! aDataSource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aResource != nullptr, "null ptr");
+ if (! aResource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ if (IsA(aDataSource, aResource, kRDF_Seq) ||
+ IsA(aDataSource, aResource, kRDF_Bag) ||
+ IsA(aDataSource, aResource, kRDF_Alt)) {
+ *_retval = true;
+ }
+ else {
+ *_retval = false;
+ }
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsEmpty(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, bool* _retval)
+{
+ if (! aDataSource)
+ return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+
+ // By default, say that we're an empty container. Even if we're not
+ // really even a container.
+ *_retval = true;
+
+ nsCOMPtr<nsIRDFNode> nextValNode;
+ rv = aDataSource->GetTarget(aResource, kRDF_nextVal, true, getter_AddRefs(nextValNode));
+ if (NS_FAILED(rv)) return rv;
+
+ if (rv == NS_RDF_NO_VALUE)
+ return NS_OK;
+
+ nsCOMPtr<nsIRDFLiteral> nextValLiteral;
+ rv = nextValNode->QueryInterface(NS_GET_IID(nsIRDFLiteral), getter_AddRefs(nextValLiteral));
+ if (NS_FAILED(rv)) return rv;
+
+ if (nextValLiteral.get() != kOne)
+ *_retval = false;
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
+{
+ NS_PRECONDITION(aDataSource != nullptr, "null ptr");
+ if (! aDataSource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aResource != nullptr, "null ptr");
+ if (! aResource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ *_retval = IsA(aDataSource, aResource, kRDF_Bag);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
+{
+ NS_PRECONDITION(aDataSource != nullptr, "null ptr");
+ if (! aDataSource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aResource != nullptr, "null ptr");
+ if (! aResource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ *_retval = IsA(aDataSource, aResource, kRDF_Seq);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IsAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, bool *_retval)
+{
+ NS_PRECONDITION(aDataSource != nullptr, "null ptr");
+ if (! aDataSource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aResource != nullptr, "null ptr");
+ if (! aResource)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(_retval != nullptr, "null ptr");
+ if (! _retval)
+ return NS_ERROR_NULL_POINTER;
+
+ *_retval = IsA(aDataSource, aResource, kRDF_Alt);
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::MakeBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
+{
+ return MakeContainer(aDataSource, aResource, kRDF_Bag, _retval);
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::MakeSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
+{
+ return MakeContainer(aDataSource, aResource, kRDF_Seq, _retval);
+}
+
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::MakeAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval)
+{
+ return MakeContainer(aDataSource, aResource, kRDF_Alt, _retval);
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+RDFContainerUtilsImpl::RDFContainerUtilsImpl()
+{
+ if (gRefCnt++ == 0) {
+ nsresult rv;
+
+ NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
+ rv = CallGetService(kRDFServiceCID, &gRDFService);
+
+ NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
+ if (NS_SUCCEEDED(rv)) {
+ gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
+ &kRDF_instanceOf);
+ gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "nextVal"),
+ &kRDF_nextVal);
+ gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Bag"),
+ &kRDF_Bag);
+ gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Seq"),
+ &kRDF_Seq);
+ gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "Alt"),
+ &kRDF_Alt);
+ gRDFService->GetLiteral(u"1", &kOne);
+ }
+ }
+}
+
+
+RDFContainerUtilsImpl::~RDFContainerUtilsImpl()
+{
+#ifdef DEBUG_REFS
+ --gInstanceCount;
+ fprintf(stdout, "%d - RDF: RDFContainerUtilsImpl\n", gInstanceCount);
+#endif
+
+ if (--gRefCnt == 0) {
+ NS_IF_RELEASE(gRDFService);
+ NS_IF_RELEASE(kRDF_instanceOf);
+ NS_IF_RELEASE(kRDF_nextVal);
+ NS_IF_RELEASE(kRDF_Bag);
+ NS_IF_RELEASE(kRDF_Seq);
+ NS_IF_RELEASE(kRDF_Alt);
+ NS_IF_RELEASE(kOne);
+ }
+}
+
+
+
+nsresult
+NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult)
+{
+ NS_PRECONDITION(aResult != nullptr, "null ptr");
+ if (! aResult)
+ return NS_ERROR_NULL_POINTER;
+
+ RDFContainerUtilsImpl* result =
+ new RDFContainerUtilsImpl();
+
+ if (! result)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ NS_ADDREF(result);
+ *aResult = result;
+ return NS_OK;
+}
+
+
+nsresult
+RDFContainerUtilsImpl::MakeContainer(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType, nsIRDFContainer** aResult)
+{
+ NS_PRECONDITION(aDataSource != nullptr, "null ptr");
+ if (! aDataSource) return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aResource != nullptr, "null ptr");
+ if (! aResource) return NS_ERROR_NULL_POINTER;
+
+ NS_PRECONDITION(aType != nullptr, "null ptr");
+ if (! aType) return NS_ERROR_NULL_POINTER;
+
+ if (aResult) *aResult = nullptr;
+
+ nsresult rv;
+
+ // Check to see if somebody has already turned it into a container; if so
+ // don't try to do it again.
+ bool isContainer;
+ rv = IsContainer(aDataSource, aResource, &isContainer);
+ if (NS_FAILED(rv)) return rv;
+
+ if (!isContainer)
+ {
+ rv = aDataSource->Assert(aResource, kRDF_instanceOf, aType, true);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = aDataSource->Assert(aResource, kRDF_nextVal, kOne, true);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ if (aResult) {
+ rv = NS_NewRDFContainer(aResult);
+ if (NS_FAILED(rv)) return rv;
+
+ rv = (*aResult)->Init(aDataSource, aResource);
+ if (NS_FAILED(rv)) return rv;
+ }
+
+ return NS_OK;
+}
+
+bool
+RDFContainerUtilsImpl::IsA(nsIRDFDataSource* aDataSource, nsIRDFResource* aResource, nsIRDFResource* aType)
+{
+ if (!aDataSource || !aResource || !aType) {
+ NS_WARNING("Unexpected null argument");
+ return false;
+ }
+
+ nsresult rv;
+
+ bool result;
+ rv = aDataSource->HasAssertion(aResource, kRDF_instanceOf, aType, true, &result);
+ if (NS_FAILED(rv))
+ return false;
+
+ return result;
+}
+
+NS_IMETHODIMP
+RDFContainerUtilsImpl::IndexOf(nsIRDFDataSource* aDataSource, nsIRDFResource* aContainer, nsIRDFNode* aElement, int32_t* aIndex)
+{
+ if (!aDataSource || !aContainer)
+ return NS_ERROR_NULL_POINTER;
+
+ // Assume we can't find it.
+ *aIndex = -1;
+
+ // If the resource is null, bail quietly
+ if (! aElement)
+ return NS_OK;
+
+ // We'll assume that fan-out is much higher than fan-in, so grovel
+ // through the inbound arcs, look for an ordinal resource, and
+ // decode it.
+ nsCOMPtr<nsISimpleEnumerator> arcsIn;
+ aDataSource->ArcLabelsIn(aElement, getter_AddRefs(arcsIn));
+ if (! arcsIn)
+ return NS_OK;
+
+ while (1) {
+ bool hasMoreArcs = false;
+ arcsIn->HasMoreElements(&hasMoreArcs);
+ if (! hasMoreArcs)
+ break;
+
+ nsCOMPtr<nsISupports> isupports;
+ arcsIn->GetNext(getter_AddRefs(isupports));
+ if (! isupports)
+ break;
+
+ nsCOMPtr<nsIRDFResource> property =
+ do_QueryInterface(isupports);
+
+ if (! property)
+ continue;
+
+ bool isOrdinal;
+ IsOrdinalProperty(property, &isOrdinal);
+ if (! isOrdinal)
+ continue;
+
+ nsCOMPtr<nsISimpleEnumerator> sources;
+ aDataSource->GetSources(property, aElement, true, getter_AddRefs(sources));
+ if (! sources)
+ continue;
+
+ while (1) {
+ bool hasMoreSources = false;
+ sources->HasMoreElements(&hasMoreSources);
+ if (! hasMoreSources)
+ break;
+
+ nsCOMPtr<nsISupports> isupports2;
+ sources->GetNext(getter_AddRefs(isupports2));
+ if (! isupports2)
+ break;
+
+ nsCOMPtr<nsIRDFResource> source =
+ do_QueryInterface(isupports2);
+
+ if (source == aContainer)
+ // Found it.
+ return OrdinalResourceToIndex(property, aIndex);
+ }
+ }
+
+ return NS_OK;
+}