зеркало из https://github.com/mozilla/gecko-dev.git
Initial revision.
This commit is contained in:
Родитель
a504a77878
Коммит
0aa56a1b36
|
@ -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;
|
||||
}
|
Загрузка…
Ссылка в новой задаче