зеркало из https://github.com/mozilla/pjs.git
Initial revision.
This commit is contained in:
Родитель
711d8c0d51
Коммит
ab34fa458b
|
@ -0,0 +1,556 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
Implementation for the RDF container.
|
||||
|
||||
*/
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIRDFContainer.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "rdf.h"
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kRDFContainerUtilsCID, NS_RDFCONTAINERUTILS_CID);
|
||||
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
|
||||
|
||||
class RDFContainerImpl : public nsIRDFContainer
|
||||
{
|
||||
public:
|
||||
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContainer interface
|
||||
NS_IMETHOD Init(nsIRDFDataSource *aDataSource, nsIRDFResource *aContainer);
|
||||
NS_IMETHOD GetCount(PRInt32 *_retval);
|
||||
NS_IMETHOD GetElements(nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD AppendElement(nsIRDFNode *aElement);
|
||||
NS_IMETHOD RemoveElement(nsIRDFNode *aElement, PRBool aRenumber);
|
||||
NS_IMETHOD InsertElementAt(nsIRDFNode *aElement, PRInt32 aIndex, PRBool aRenumber);
|
||||
NS_IMETHOD IndexOf(nsIRDFNode *aElement, PRInt32 *_retval);
|
||||
|
||||
private:
|
||||
friend nsresult NS_NewRDFContainer(nsIRDFContainer** aResult);
|
||||
|
||||
RDFContainerImpl();
|
||||
virtual ~RDFContainerImpl();
|
||||
|
||||
nsresult Renumber(PRInt32 aStartIndex);
|
||||
nsresult SetNextValue(PRInt32 aIndex);
|
||||
nsresult GetNextValue(nsIRDFResource** aResult);
|
||||
|
||||
nsIRDFDataSource* mDataSource;
|
||||
nsIRDFResource* mContainer;
|
||||
|
||||
// pseudo constants
|
||||
static PRInt32 gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFContainerUtils* gRDFContainerUtils;
|
||||
static nsIRDFResource* kRDF_nextVal;
|
||||
};
|
||||
|
||||
|
||||
PRInt32 RDFContainerImpl::gRefCnt = 0;
|
||||
nsIRDFService* RDFContainerImpl::gRDFService;
|
||||
nsIRDFContainerUtils* RDFContainerImpl::gRDFContainerUtils;
|
||||
nsIRDFResource* RDFContainerImpl::kRDF_nextVal;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports interface
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFContainerImpl, nsIRDFContainer::GetIID());
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFContainer interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::Init(nsIRDFDataSource *aDataSource, nsIRDFResource *aContainer)
|
||||
{
|
||||
NS_PRECONDITION(aDataSource != nsnull, "null ptr");
|
||||
if (! aDataSource)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aContainer != nsnull, "null ptr");
|
||||
if (! aContainer)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_IF_RELEASE(mDataSource);
|
||||
mDataSource = aDataSource;
|
||||
NS_ADDREF(mDataSource);
|
||||
|
||||
NS_IF_RELEASE(mContainer);
|
||||
mContainer = aContainer;
|
||||
NS_ADDREF(mContainer);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::GetCount(PRInt32 *aCount)
|
||||
{
|
||||
NS_PRECONDITION(aCount != nsnull, "null ptr");
|
||||
if (! aCount)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Get the next value, which hangs off of the bag via the
|
||||
// RDF:nextVal property.
|
||||
nsCOMPtr<nsIRDFNode> nextValNode;
|
||||
rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, PR_TRUE, getter_AddRefs(nextValNode));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_NO_VALUE)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> nextValLiteral;
|
||||
rv = nextValNode->QueryInterface(nsIRDFLiteral::GetIID(), getter_AddRefs(nextValLiteral));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLString s;
|
||||
rv = nextValLiteral->GetValue( getter_Copies(s) );
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString nextValStr = (const PRUnichar*) s;
|
||||
|
||||
PRInt32 err;
|
||||
*aCount = nextValStr.ToInteger(&err);
|
||||
if (NS_FAILED(err))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::GetElements(nsISimpleEnumerator **_retval)
|
||||
{
|
||||
return NS_NewContainerEnumerator(mDataSource, mContainer, _retval);
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::AppendElement(nsIRDFNode *aElement)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRBool isContainer;
|
||||
rv = gRDFContainerUtils->IsContainer(mDataSource, mContainer, &isContainer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_PRECONDITION(isContainer, "not a container");
|
||||
if (! isContainer)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> nextVal;
|
||||
rv = GetNextValue(getter_AddRefs(nextVal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDataSource->Assert(mContainer, nextVal, aElement, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::RemoveElement(nsIRDFNode *aElement, PRBool aRenumber)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 index;
|
||||
rv = IndexOf(aElement, &index);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (index < 0) {
|
||||
NS_WARNING("attempt to remove non-existant element");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Remove the element.
|
||||
nsCOMPtr<nsIRDFResource> ordinal;
|
||||
rv = gRDFContainerUtils->IndexToOrdinalResource(index, getter_AddRefs(ordinal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDataSource->Unassert(mContainer, ordinal, aElement);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aRenumber) {
|
||||
// Now slide the rest of the collection backwards to fill in
|
||||
// the gap. This will have the side effect of completely
|
||||
// renumber the container from index to the end.
|
||||
rv = Renumber(index);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::InsertElementAt(nsIRDFNode *aElement, PRInt32 aIndex, PRBool aRenumber)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aIndex >= 1, "illegal value");
|
||||
if (aIndex < 1)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = GetCount(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
NS_ASSERTION(aIndex <= count, "illegal value");
|
||||
if (aIndex > count)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
if (aRenumber) {
|
||||
// Make a hole for the element. This will have the side effect of
|
||||
// completely renumbering the container from 'aIndex' to 'count',
|
||||
// and will spew assertions.
|
||||
rv = Renumber(aIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRDFResource> ordinal;
|
||||
rv = gRDFContainerUtils->IndexToOrdinalResource(aIndex, getter_AddRefs(ordinal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDataSource->Assert(mContainer, ordinal, aElement, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerImpl::IndexOf(nsIRDFNode *aElement, PRInt32 *aIndex)
|
||||
{
|
||||
NS_PRECONDITION(aElement != nsnull, "null ptr");
|
||||
if (! aElement)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
NS_PRECONDITION(aIndex != nsnull, "null ptr");
|
||||
if (! aIndex)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = GetCount(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 index = 0; index < count; ++index) {
|
||||
nsCOMPtr<nsIRDFResource> ordinal;
|
||||
rv = gRDFContainerUtils->IndexToOrdinalResource(index, getter_AddRefs(ordinal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Get all of the elements in the container with the specified
|
||||
// ordinal. This is an ultra-paranoid way to do it, but -- due
|
||||
// to aggregation, we may end up with a container that has >1
|
||||
// element for the same ordinal.
|
||||
nsCOMPtr<nsISimpleEnumerator> targets;
|
||||
rv = mDataSource->GetTargets(mContainer, ordinal, PR_TRUE, getter_AddRefs(targets));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMore;
|
||||
rv = targets->HasMoreElements(&hasMore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasMore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = targets->GetNext(getter_AddRefs(isupports));
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to read cursor");
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> element = do_QueryInterface(isupports);
|
||||
|
||||
if (element.get() != aElement)
|
||||
continue;
|
||||
|
||||
// Okay, we've found it!
|
||||
*aIndex = index;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
NS_WARNING("element not found");
|
||||
*aIndex = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RDFContainerImpl::RDFContainerImpl()
|
||||
: mDataSource(nsnull), mContainer(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
if (gRefCnt++ == 0) {
|
||||
nsresult rv;
|
||||
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
nsIRDFService::GetIID(),
|
||||
(nsISupports**) &gRDFService);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "nextVal", &kRDF_nextVal);
|
||||
}
|
||||
|
||||
rv = nsServiceManager::GetService(kRDFContainerUtilsCID,
|
||||
nsIRDFContainerUtils::GetIID(),
|
||||
(nsISupports**) &gRDFContainerUtils);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF container utils service");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RDFContainerImpl::~RDFContainerImpl()
|
||||
{
|
||||
NS_IF_RELEASE(mContainer);
|
||||
NS_IF_RELEASE(mDataSource);
|
||||
|
||||
if (--gRefCnt == 0) {
|
||||
nsServiceManager::ReleaseService(kRDFContainerUtilsCID, gRDFContainerUtils);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
NS_NewRDFContainer(nsIRDFContainer** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
RDFContainerImpl* result =
|
||||
new RDFContainerImpl();
|
||||
|
||||
if (! result)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(result);
|
||||
*aResult = result;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
NS_NewRDFContainer(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* aResource,
|
||||
nsIRDFContainer** aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = NS_NewRDFContainer(aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = (*aResult)->Init(aDataSource, aResource);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_RELEASE(*aResult);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFContainerImpl::Renumber(PRInt32 aStartIndex)
|
||||
{
|
||||
// Renumber the elements in the container
|
||||
nsresult rv;
|
||||
|
||||
PRInt32 count;
|
||||
rv = GetCount(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 oldIndex = aStartIndex;
|
||||
PRInt32 newIndex = aStartIndex;
|
||||
while (oldIndex < count) {
|
||||
nsCOMPtr<nsIRDFResource> oldOrdinal;
|
||||
rv = gRDFContainerUtils->IndexToOrdinalResource(oldIndex, getter_AddRefs(oldOrdinal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Because of aggregation, we need to be paranoid about
|
||||
// the possibility that >1 element may be present per
|
||||
// ordinal.
|
||||
nsCOMPtr<nsISimpleEnumerator> targets;
|
||||
rv = mDataSource->GetTargets(mContainer, oldOrdinal, PR_TRUE, getter_AddRefs(targets));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
while (1) {
|
||||
PRBool hasMore;
|
||||
rv = targets->HasMoreElements(&hasMore);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (! hasMore)
|
||||
break;
|
||||
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
rv = targets->GetNext(getter_AddRefs(isupports));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFNode> element( do_QueryInterface(isupports) );
|
||||
NS_ASSERTION(element != nsnull, "something funky in the enumerator");
|
||||
if (! element)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
rv = mDataSource->Unassert(mContainer, oldOrdinal, element);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFResource> newOrdinal;
|
||||
rv = gRDFContainerUtils->IndexToOrdinalResource(++newIndex, getter_AddRefs(newOrdinal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDataSource->Assert(mContainer, newOrdinal, element, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the container's nextVal to reflect the renumbering
|
||||
rv = SetNextValue(++newIndex);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
RDFContainerImpl::SetNextValue(PRInt32 aIndex)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
// Remove the current value of nextVal, if there is one.
|
||||
nsCOMPtr<nsIRDFNode> nextValNode;
|
||||
if (NS_SUCCEEDED(rv = mDataSource->GetTarget(mContainer,
|
||||
kRDF_nextVal,
|
||||
PR_TRUE,
|
||||
getter_AddRefs(nextValNode)))) {
|
||||
if (NS_FAILED(rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValNode))) {
|
||||
NS_ERROR("unable to update nextVal");
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString s;
|
||||
s.Append(aIndex, 10);
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> nextVal;
|
||||
if (NS_FAILED(rv = gRDFService->GetLiteral(s.GetUnicode(), getter_AddRefs(nextVal)))) {
|
||||
NS_ERROR("unable to get nextVal literal");
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextVal, PR_TRUE);
|
||||
if (rv != NS_RDF_ASSERTION_ACCEPTED) {
|
||||
NS_ERROR("unable to update nextVal");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
RDFContainerImpl::GetNextValue(nsIRDFResource** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "null ptr");
|
||||
if (! aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv;
|
||||
|
||||
// Get the next value, which hangs off of the bag via the
|
||||
// RDF:nextVal property.
|
||||
nsCOMPtr<nsIRDFNode> nextValNode;
|
||||
rv = mDataSource->GetTarget(mContainer, kRDF_nextVal, PR_TRUE, getter_AddRefs(nextValNode));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (rv == NS_RDF_NO_VALUE)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> nextValLiteral;
|
||||
rv = nextValNode->QueryInterface(nsIRDFLiteral::GetIID(), getter_AddRefs(nextValLiteral));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsXPIDLString s;
|
||||
rv = nextValLiteral->GetValue( getter_Copies(s) );
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsAutoString nextValStr = (const PRUnichar*) s;
|
||||
|
||||
PRInt32 err;
|
||||
PRInt32 nextVal = nextValStr.ToInteger(&err);
|
||||
if (NS_FAILED(err))
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Generate a URI that we can return.
|
||||
nextValStr = kRDFNameSpaceURI;
|
||||
nextValStr.Append("_");
|
||||
nextValStr.Append(nextVal, 10);
|
||||
|
||||
rv = gRDFService->GetUnicodeResource(nextValStr.GetUnicode(), aResult);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
// Now increment the RDF:nextVal property.
|
||||
rv = mDataSource->Unassert(mContainer, kRDF_nextVal, nextValLiteral);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
++nextVal;
|
||||
nextValStr.Truncate();
|
||||
nextValStr.Append(nextVal, 10);
|
||||
|
||||
rv = gRDFService->GetLiteral(nextValStr.GetUnicode(), getter_AddRefs(nextValLiteral));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = mDataSource->Assert(mContainer, kRDF_nextVal, nextValLiteral, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,362 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
* the License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape Communications
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
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"
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
|
||||
|
||||
class RDFContainerUtilsImpl : public nsIRDFContainerUtils
|
||||
{
|
||||
public:
|
||||
// nsISupports interface
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIRDFContainerUtils interface
|
||||
NS_IMETHOD IsOrdinalProperty(nsIRDFResource *aProperty, PRBool *_retval);
|
||||
NS_IMETHOD IndexToOrdinalResource(PRInt32 aIndex, nsIRDFResource **_retval);
|
||||
NS_IMETHOD OrdinalResourceToIndex(nsIRDFResource *aOrdinal, PRInt32 *_retval);
|
||||
NS_IMETHOD IsContainer(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval);
|
||||
NS_IMETHOD IsBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval);
|
||||
NS_IMETHOD IsSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval);
|
||||
NS_IMETHOD IsAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval);
|
||||
NS_IMETHOD MakeBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval);
|
||||
NS_IMETHOD MakeSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval);
|
||||
NS_IMETHOD MakeAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, nsIRDFContainer **_retval);
|
||||
|
||||
private:
|
||||
friend nsresult NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult);
|
||||
|
||||
RDFContainerUtilsImpl();
|
||||
virtual ~RDFContainerUtilsImpl();
|
||||
|
||||
nsresult MakeContainer(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* aResource,
|
||||
nsIRDFResource* aType,
|
||||
nsIRDFContainer** aResult);
|
||||
|
||||
// pseudo constants
|
||||
static PRInt32 gRefCnt;
|
||||
static nsIRDFService* gRDFService;
|
||||
static nsIRDFResource* kRDF_instanceOf;
|
||||
static nsIRDFResource* kRDF_nextVal;
|
||||
static nsIRDFResource* kRDF_Bag;
|
||||
static nsIRDFResource* kRDF_Seq;
|
||||
static nsIRDFResource* kRDF_Alt;
|
||||
};
|
||||
|
||||
|
||||
PRInt32 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;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsISupports interface
|
||||
|
||||
NS_IMPL_ISUPPORTS(RDFContainerUtilsImpl, nsIRDFContainerUtils::GetIID());
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// nsIRDFContainerUtils interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IsOrdinalProperty(nsIRDFResource *aProperty, PRBool *_retval)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsXPIDLCString propertyStr;
|
||||
rv = aProperty->GetValue( getter_Copies(propertyStr) );
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (PL_strncmp(propertyStr, kRDFNameSpaceURI, sizeof(kRDFNameSpaceURI) - 1) != 0) {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
const char* s = propertyStr;
|
||||
s += sizeof(kRDFNameSpaceURI) - 1;
|
||||
if (*s != '_') {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
++s;
|
||||
while (*s) {
|
||||
if (*s < '0' || *s > '9') {
|
||||
*_retval = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
++s;
|
||||
}
|
||||
|
||||
*_retval = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IndexToOrdinalResource(PRInt32 aIndex, nsIRDFResource **aOrdinal)
|
||||
{
|
||||
NS_PRECONDITION(aIndex > 0, "illegal value");
|
||||
if (aIndex <= 0)
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
|
||||
// 16 digits should be plenty to hold a decimal version of a
|
||||
// PRInt32.
|
||||
char buf[sizeof(kRDFNameSpaceURI) + 16 + 1];
|
||||
|
||||
PL_strcpy(buf, kRDFNameSpaceURI);
|
||||
buf[sizeof(kRDFNameSpaceURI) - 1] = '_';
|
||||
|
||||
PR_snprintf(buf + sizeof(kRDFNameSpaceURI), 16, "%ld", aIndex);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
rv = gRDFService->GetResource(buf, 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, PRInt32 *aIndex)
|
||||
{
|
||||
nsXPIDLCString ordinalStr;
|
||||
if (NS_FAILED(aOrdinal->GetValue( getter_Copies(ordinalStr) )))
|
||||
return PR_FALSE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
PRInt32 index = 0;
|
||||
|
||||
++s;
|
||||
while (*s) {
|
||||
if (*s < '0' || *s > '9') {
|
||||
NS_ERROR("not an ordinal");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
index *= 10;
|
||||
index += (*s - '0');
|
||||
|
||||
++s;
|
||||
}
|
||||
|
||||
*aIndex = index;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IsContainer(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nsnull, "null ptr");
|
||||
if (! _retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if (rdf_IsA(aDataSource, aResource, kRDF_Bag) ||
|
||||
rdf_IsA(aDataSource, aResource, kRDF_Seq) ||
|
||||
rdf_IsA(aDataSource, aResource, kRDF_Alt)) {
|
||||
*_retval = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
*_retval = PR_FALSE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IsBag(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nsnull, "null ptr");
|
||||
if (! _retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = rdf_IsA(aDataSource, aResource, kRDF_Bag);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IsSeq(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nsnull, "null ptr");
|
||||
if (! _retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = rdf_IsA(aDataSource, aResource, kRDF_Seq);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
RDFContainerUtilsImpl::IsAlt(nsIRDFDataSource *aDataSource, nsIRDFResource *aResource, PRBool *_retval)
|
||||
{
|
||||
NS_PRECONDITION(_retval != nsnull, "null ptr");
|
||||
if (! _retval)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*_retval = rdf_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()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
if (gRefCnt++ == 0) {
|
||||
nsresult rv;
|
||||
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
nsIRDFService::GetIID(),
|
||||
(nsISupports**) &gRDFService);
|
||||
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to get RDF service");
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "instanceOf", &kRDF_instanceOf);
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "nextVal", &kRDF_nextVal);
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "Bag", &kRDF_Bag);
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "Seq", &kRDF_Seq);
|
||||
gRDFService->GetResource(RDF_NAMESPACE_URI "Alt", &kRDF_Alt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
RDFContainerUtilsImpl::~RDFContainerUtilsImpl()
|
||||
{
|
||||
if (--gRefCnt == 0) {
|
||||
if (gRDFService) {
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, gRDFService);
|
||||
gRDFService = nsnull;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_NewRDFContainerUtils(nsIRDFContainerUtils** aResult)
|
||||
{
|
||||
NS_PRECONDITION(aResult != nsnull, "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)
|
||||
{
|
||||
nsresult rv;
|
||||
rv = aDataSource->Assert(aResource, kRDF_instanceOf, aType, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIRDFLiteral> nextVal;
|
||||
rv = gRDFService->GetLiteral(nsAutoString("1").GetUnicode(), getter_AddRefs(nextVal));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aDataSource->Assert(aResource, kRDF_nextVal, nextVal, PR_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;
|
||||
}
|
||||
|
Загрузка…
Ссылка в новой задаче