This commit is contained in:
waterson%netscape.com 1998-12-15 04:03:24 +00:00
Родитель a504a77878
Коммит 0aa56a1b36
2 изменённых файлов: 370 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,216 @@
/* -*- 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 "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nscore.h"
#include "nsIRDFCursor.h"
#include "nsIRDFDataSource.h"
#include "nsIRDFNode.h"
#include "nsIRDFResourceManager.h"
#include "nsIServiceManager.h"
#include "nsRDFCID.h"
#include "nsString.h"
#include "prlog.h"
#include "rdf.h"
#include "rdfutil.h"
/*
A simple cursor that enumerates the elements of a container.
Caveats
-------
1. This uses an implementation-specific detail to determine the
index of the last element in the container; specifically, the RDF
utilities maintain a counter attribute on the container that
holds the numeric value of the next value that is to be
assigned. So, this cursor will bust if you use it with a bag that
hasn't been created using the RDF utility routines.
2. This is sort of a continuation of (1), but -- it's not smart
enough to notice duplicates.
TODO. This is way too brain dead to handle aggregated RDF
databases. It needs to be upgraded in a big way.
*/
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID);
static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID);
////////////////////////////////////////////////////////////////////////
#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#"
static const char kRDFNameSpaceURI[] = RDF_NAMESPACE_URI;
DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, nextVal); // ad hoc way to make containers fast
////////////////////////////////////////////////////////////////////////
class ContainerCursorImpl : public nsIRDFCursor {
private:
nsIRDFResourceManager* mResourceMgr;
nsIRDFDataSource* mDataSource;
nsIRDFNode* mContainer;
nsIRDFNode* mNext;
PRInt32 mCounter;
void SkipToNext(void);
public:
ContainerCursorImpl(nsIRDFDataSource* ds, nsIRDFNode* container);
virtual ~ContainerCursorImpl(void);
NS_DECL_ISUPPORTS
NS_IMETHOD HasMoreElements(PRBool& result);
NS_IMETHOD GetNext(nsIRDFNode*& next, PRBool& tv);
};
ContainerCursorImpl::ContainerCursorImpl(nsIRDFDataSource* ds,
nsIRDFNode* container)
: mDataSource(ds), mContainer(container), mNext(nsnull), mCounter(1)
{
NS_ASSERTION(ds != nsnull, "null ptr");
NS_ASSERTION(container != nsnull, "null ptr");
NS_IF_ADDREF(mDataSource);
NS_IF_ADDREF(mContainer);
nsresult rv;
rv = nsServiceManager::GetService(kRDFResourceManagerCID,
kIRDFResourceManagerIID,
(nsISupports**) &mResourceMgr);
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to acquire resource manager");
NS_ASSERTION(rdf_IsContainer(mResourceMgr, mDataSource, container), "not a container");
SkipToNext();
}
ContainerCursorImpl::~ContainerCursorImpl(void)
{
NS_IF_RELEASE(mNext);
if (mResourceMgr)
nsServiceManager::ReleaseService(kRDFResourceManagerCID, mResourceMgr);
NS_IF_RELEASE(mContainer);
NS_IF_RELEASE(mDataSource);
}
static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID);
NS_IMPL_ISUPPORTS(ContainerCursorImpl, kIRDFCursorIID);
NS_IMETHODIMP
ContainerCursorImpl::HasMoreElements(PRBool& result)
{
return (mNext != nsnull);
}
NS_IMETHODIMP
ContainerCursorImpl::GetNext(nsIRDFNode*& next, PRBool& tv)
{
if (! mNext)
return NS_ERROR_UNEXPECTED;
next = mNext; // no need to addref, SkipToNext() did it
tv = PR_TRUE;
SkipToNext();
return NS_OK;
}
void
ContainerCursorImpl::SkipToNext(void)
{
if (!mDataSource || !mContainer)
return;
nsresult rv;
mNext = nsnull;
nsIRDFNode* RDF_nextVal = nsnull;
nsIRDFNode* nextVal = nsnull;
nsAutoString next;
PRInt32 last;
PRInt32 err;
// XXX we could cache all this crap when the cursor gets created.
if (NS_FAILED(rv = mResourceMgr->GetNode(kURIRDF_nextVal, RDF_nextVal)))
goto done;
if (NS_FAILED(rv = mDataSource->GetTarget(mContainer, RDF_nextVal, PR_TRUE, nextVal)))
goto done;
if (NS_FAILED(rv = nextVal->GetStringValue(next)))
goto done;
last = next.ToInteger(&err);
if (NS_FAILED(err))
goto done;
while (mCounter < last) {
next = kRDFNameSpaceURI;
next.Append("_");
next.Append(mCounter, 10);
nsIRDFNode* ordinalProperty = nsnull;
if (NS_FAILED(rv = mResourceMgr->GetNode(next, ordinalProperty)))
break;
rv = mDataSource->GetTarget(mContainer, ordinalProperty, PR_TRUE, mNext);
NS_IF_RELEASE(ordinalProperty);
if (NS_SUCCEEDED(rv)) {
// Don't bother releasing mNext; we'll let the AddRef
// serve as the implicit addref that GetNext() should
// perform.
break;
}
++mCounter;
}
done:
NS_IF_RELEASE(nextVal);
NS_IF_RELEASE(RDF_nextVal);
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewContainerCursor(nsIRDFDataSource* ds,
nsIRDFNode* container,
nsIRDFCursor*& cursor)
{
nsIRDFCursor* result = new ContainerCursorImpl(ds, container);
if (! result)
return NS_ERROR_OUT_OF_MEMORY;
cursor = result;
NS_ADDREF(cursor);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,154 @@
/* -*- 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 "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
A data source that can read itself from and write itself to a stream.
*/
#include "nsIDTD.h"
#include "nsINameSpaceManager.h"
#include "nsIParser.h"
#include "nsIRDFContentSink.h"
#include "nsIStreamListener.h"
#include "nsIURL.h"
#include "nsMemoryDataSource.h"
#include "nsParserCIID.h"
////////////////////////////////////////////////////////////////////////
static NS_DEFINE_IID(kIDTDIID, NS_IDTD_IID);
static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_CID(kParserCID, NS_PARSER_IID); // XXX
static NS_DEFINE_CID(kWellFormedDTDCID, NS_WELLFORMEDDTD_CID);
////////////////////////////////////////////////////////////////////////
class StreamDataSourceImpl : public nsMemoryDataSource
{
protected:
nsIURL* mURL;
public:
StreamDataSourceImpl(void);
virtual ~StreamDataSourceImpl(void);
// nsIDataSource methods that are overloaded from nsMemoryDataSource
NS_IMETHOD Init(const nsString& uri);
NS_IMETHOD Flush(void);
};
////////////////////////////////////////////////////////////////////////
StreamDataSourceImpl::StreamDataSourceImpl(void)
: mURL(nsnull)
{
}
StreamDataSourceImpl::~StreamDataSourceImpl(void)
{
NS_IF_RELEASE(mURL);
}
NS_IMETHODIMP
StreamDataSourceImpl::Init(const nsString& uri)
{
nsresult rv;
if (NS_FAILED(rv = NS_NewURL(&mURL, uri)))
return rv;
nsINameSpaceManager* ns = nsnull;
nsIRDFContentSink* sink = nsnull;
nsIParser* parser = nsnull;
nsIDTD* dtd = nsnull;
nsIStreamListener* lsnr = nsnull;
// XXX Get a namespace manager *here*
PR_ASSERT(0);
if (NS_FAILED(rv = NS_NewRDFSimpleContentSink(&sink, mURL, ns)))
goto done;
if (NS_FAILED(rv = sink->SetDataSource(this)))
goto done;
if (NS_FAILED(rv = nsRepository::CreateInstance(kParserCID,
nsnull,
kIParserIID,
(void**) &parser)))
goto done;
parser->SetContentSink(sink);
if (NS_FAILED(rv = nsRepository::CreateInstance(kWellFormedDTDCID,
nsnull,
kIDTDIID,
(void**) &dtd)))
goto done;
parser->RegisterDTD(dtd);
if (NS_FAILED(rv = parser->QueryInterface(kIStreamListenerIID, (void**) &lsnr)))
goto done;
// XXX This _can't_ be all I need to do -- how do I start the parser?
if (NS_FAILED(parser->Parse(mURL)))
goto done;
if (NS_FAILED(mURL->Open(lsnr)))
goto done;
done:
NS_IF_RELEASE(lsnr);
NS_IF_RELEASE(dtd);
NS_IF_RELEASE(parser);
NS_IF_RELEASE(sink);
return rv;
}
NS_IMETHODIMP
StreamDataSourceImpl::Flush(void)
{
// XXX walk through all the resources, writing <RDF:Description>
// elements with properties for each.
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
nsresult
NS_NewRDFStreamDataSource(nsIRDFDataSource** result)
{
StreamDataSourceImpl* ds = new StreamDataSourceImpl();
if (! ds)
return NS_ERROR_NULL_POINTER;
*result = ds;
NS_ADDREF(*result);
return NS_OK;
}