From 5ca3227fb566b0beac8672a5497b87674097c710 Mon Sep 17 00:00:00 2001 From: "waterson%netscape.com" Date: Tue, 1 Dec 1998 03:01:35 +0000 Subject: [PATCH] Landed changes from RDF_19981124_BRANCH. This is still not in the build. --- rdf/include/makefile.win | 11 +- rdf/include/nsIRDFCursor.h | 7 +- rdf/include/nsIRDFDataBase.h | 48 +- rdf/include/nsIRDFDataSource.h | 273 ++--- rdf/include/nsIRDFNode.h | 66 + rdf/include/nsIRDFObserver.h | 7 +- rdf/include/nsIRDFRegistry.h | 57 + rdf/include/nsIRDFResourceManager.h | 37 + rdf/include/nsRDFCID.h | 33 +- rdf/include/rdf.h | 31 +- rdf/src/comwrap.cpp | 712 ----------- rdf/src/makefile.win | 64 +- rdf/src/nsBookmarkDataSource.cpp | 584 +++++++++ rdf/src/nsBookmarkDataSource.h | 39 + rdf/src/nsEmptyCursor.cpp | 91 ++ rdf/src/nsIRDFContent.h | 46 + rdf/src/nsIRDFContentSink.h | 64 + rdf/src/nsIRDFDocument.h | 44 + rdf/src/nsMemoryDataSource.cpp | 730 +++++++++++ rdf/src/nsMemoryDataSource.h | 97 ++ rdf/src/nsRDFContentSink.cpp | 1615 +++++++++++++++++++++++++ rdf/src/nsRDFContentSink.h | 153 +++ rdf/src/nsRDFDataModel.cpp | 213 ---- rdf/src/nsRDFDataModel.h | 99 -- rdf/src/nsRDFDataModelItem.cpp | 262 ---- rdf/src/nsRDFDataModelItem.h | 118 -- rdf/src/nsRDFDocument.cpp | 311 +++++ rdf/src/nsRDFDocument.h | 76 ++ rdf/src/nsRDFElement.cpp | 1472 ++++++++++++++++++++++ rdf/src/nsRDFElement.h | 140 +++ rdf/src/nsRDFFactory.cpp | 57 +- rdf/src/nsRDFRegistryImpl.cpp | 109 ++ rdf/src/nsRDFRegistryImpl.h | 42 + rdf/src/nsRDFResourceManager.cpp | 177 +++ rdf/src/nsRDFResourceManager.h | 46 + rdf/src/nsRDFToolbarDataModel.cpp | 131 -- rdf/src/nsRDFToolbarDataModel.h | 75 -- rdf/src/nsRDFToolbarDataModelItem.cpp | 133 -- rdf/src/nsRDFToolbarDataModelItem.h | 77 -- rdf/src/nsRDFTreeColumn.cpp | 173 --- rdf/src/nsRDFTreeColumn.h | 79 -- rdf/src/nsRDFTreeDataModel.cpp | 395 ------ rdf/src/nsRDFTreeDataModel.h | 93 -- rdf/src/nsRDFTreeDataModelItem.cpp | 160 --- rdf/src/nsRDFTreeDataModelItem.h | 86 -- rdf/src/nsSimpleDataBase.cpp | 638 ++++++++++ rdf/src/nsSimpleDataBase.h | 92 ++ 47 files changed, 6970 insertions(+), 3093 deletions(-) create mode 100644 rdf/include/nsIRDFNode.h create mode 100644 rdf/include/nsIRDFRegistry.h create mode 100644 rdf/include/nsIRDFResourceManager.h delete mode 100644 rdf/src/comwrap.cpp create mode 100644 rdf/src/nsBookmarkDataSource.cpp create mode 100644 rdf/src/nsBookmarkDataSource.h create mode 100644 rdf/src/nsEmptyCursor.cpp create mode 100644 rdf/src/nsIRDFContent.h create mode 100644 rdf/src/nsIRDFContentSink.h create mode 100644 rdf/src/nsIRDFDocument.h create mode 100644 rdf/src/nsMemoryDataSource.cpp create mode 100644 rdf/src/nsMemoryDataSource.h create mode 100644 rdf/src/nsRDFContentSink.cpp create mode 100644 rdf/src/nsRDFContentSink.h delete mode 100644 rdf/src/nsRDFDataModel.cpp delete mode 100644 rdf/src/nsRDFDataModel.h delete mode 100644 rdf/src/nsRDFDataModelItem.cpp delete mode 100644 rdf/src/nsRDFDataModelItem.h create mode 100644 rdf/src/nsRDFDocument.cpp create mode 100644 rdf/src/nsRDFDocument.h create mode 100644 rdf/src/nsRDFElement.cpp create mode 100644 rdf/src/nsRDFElement.h create mode 100644 rdf/src/nsRDFRegistryImpl.cpp create mode 100644 rdf/src/nsRDFRegistryImpl.h create mode 100644 rdf/src/nsRDFResourceManager.cpp create mode 100644 rdf/src/nsRDFResourceManager.h delete mode 100644 rdf/src/nsRDFToolbarDataModel.cpp delete mode 100644 rdf/src/nsRDFToolbarDataModel.h delete mode 100644 rdf/src/nsRDFToolbarDataModelItem.cpp delete mode 100644 rdf/src/nsRDFToolbarDataModelItem.h delete mode 100644 rdf/src/nsRDFTreeColumn.cpp delete mode 100644 rdf/src/nsRDFTreeColumn.h delete mode 100644 rdf/src/nsRDFTreeDataModel.cpp delete mode 100644 rdf/src/nsRDFTreeDataModel.h delete mode 100644 rdf/src/nsRDFTreeDataModelItem.cpp delete mode 100644 rdf/src/nsRDFTreeDataModelItem.h create mode 100644 rdf/src/nsSimpleDataBase.cpp create mode 100644 rdf/src/nsSimpleDataBase.h diff --git a/rdf/include/makefile.win b/rdf/include/makefile.win index 713861575c69..e4fce56cd5c4 100644 --- a/rdf/include/makefile.win +++ b/rdf/include/makefile.win @@ -23,11 +23,14 @@ DEPTH = ..\.. EXPORTS = rdf.h \ rdfc.h \ - nsIRDFService.h \ - nsIRDFDataSource.h \ - nsIRDFDataBase.h \ - nsIRDFObserver.h \ nsIRDFCursor.h \ + nsIRDFDataBase.h \ + nsIRDFDataSource.h \ + nsIRDFNode.h \ + nsIRDFObserver.h \ + nsIRDFRegistry.h \ + nsIRDFResourceManager.h \ + nsIRDFService.h \ nsRDFCID.h \ htrdf.h \ vocab.h \ diff --git a/rdf/include/nsIRDFCursor.h b/rdf/include/nsIRDFCursor.h index 138e31acf096..f899911dcc7f 100644 --- a/rdf/include/nsIRDFCursor.h +++ b/rdf/include/nsIRDFCursor.h @@ -44,10 +44,13 @@ class nsIRDFCursor : public nsISupports { public: - NS_IMETHOD HasElements(PRBool& hasElements) = 0; + NS_IMETHOD HasMoreElements(PRBool& result /* out */) = 0; - NS_IMETHOD Next(RDF_NodeStruct& next /* in/out */) = 0; + // XXX If the node struct contains an nsIAtom, did you refcount it + // before returning? + NS_IMETHOD GetNext(nsIRDFNode*& next /* in/out */, + PRBool& tv /* out */) = 0; }; #endif /* nsIRDFCursor_h__ */ diff --git a/rdf/include/nsIRDFDataBase.h b/rdf/include/nsIRDFDataBase.h index b222dfbd5b93..9bea1043574b 100644 --- a/rdf/include/nsIRDFDataBase.h +++ b/rdf/include/nsIRDFDataBase.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* -*- 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 @@ -20,54 +20,30 @@ #define nsIRDFDataBase_h__ /* - This file contains the interface definition for an RDF database. RDF databases aggregate RDF data sources (see nsIRDFDataSource.h) + + XXX This needs to be thought about real hard. It seems really wrong + to me to have to hard code the data sources that a database knows + about. + */ #include "nsISupports.h" #include "nsIRDFDataSource.h" -#include "rdf.h" +class nsIRDFDataSource; // 96343820-307c-11d2-bc15-00805f912fe7 #define NS_IRDFDATABASE_IID \ -{ \ - 0x96343820, \ - 0x307c, \ - 0x11d2, \ - { 0xb, 0x15, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } \ -} - +{ 0x96343820, 0x307c, 0x11d2, { 0xb, 0x15, 0x00, 0x80, 0x5f, 0x91, 0x2f, 0xe7 } } class nsIRDFDataBase : public nsIRDFDataSource { public: - -#ifdef RDF_NOT_IMPLEMENTED - NS_IMETHOD Initialize(nsIRDFResourceManager* r) = 0; -#endif - - -#ifdef RDF_NOT_IMPLEMENTED - /* - Add a data source for the specified URL to the database. - - Parameters: - dataSource -- a ptr to the data source to add - - Returns: - */ - NS_IMETHOD AddDataSource(nsIRDFDataSource* dataSource) = 0; - - NS_IMETHOD RemoveDataSource(nsIRDFDataSource* dataSource) = 0; - - NS_IMETHOD GetDataSource(RDF_String url, - nsIRDFDataSource **source /* out */ ) = 0; -#endif - - // XXX move these to datasource? - NS_IMETHOD DeleteAllArcs(RDF_Resource resource) = 0; - + // XXX This is really a hack. I wish that the database was just a + // plain old data source that was smart import the data sources + // that it needed. + NS_IMETHOD AddDataSource(nsIRDFDataSource* source) = 0; }; diff --git a/rdf/include/nsIRDFDataSource.h b/rdf/include/nsIRDFDataSource.h index 5642b6706deb..2b71fa4f67ae 100644 --- a/rdf/include/nsIRDFDataSource.h +++ b/rdf/include/nsIRDFDataSource.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +/* -*- 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 @@ -21,209 +21,124 @@ /* This file contains the interface definition for an RDF data source. - - Classes which implement this interface for a particular type of URL - are registered with the RDF singleton via nsIRDF::RegisterHandler(...) */ #include "nsISupports.h" -#include "rdf.h" -// 852666b0-2cce-11d2-bc14-00805f912fe7 +// {0F78DA58-8321-11d2-8EAC-00805F29F370} #define NS_IRDFDATASOURCE_IID \ -{ \ - 0x852666b0, \ - 0x2cce, \ - 0x11d2, \ - { 0xb, 0xc14,0x00, 0x80, 0x5f, 0x91 0x2f, 0xe7 } \ -} +{ 0xf78da58, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } +class nsIRDFNode; class nsIRDFCursor; class nsIRDFObserver; class nsIRDFDataBase; +class nsString; + +// XXX I didn't make any of these methods "const" because it's +// probably pretty likely that many data sources will just make stuff +// up at runtime to answer queries. class nsIRDFDataSource : public nsISupports { public: + /** + * Specify the URI for the data source: this is the prefix + * that will be used to register the data source in the + * data source registry. + */ + NS_IMETHOD Initialize(const nsString& uri) = 0; -#ifdef RDF_NOT_IMPLEMENTED - /** - * Initialize this data source - */ - NS_IMETHOD Initialize(RDF_String url, - nsIRDFResourceManager* m); -#endif + /** + * Find an RDF resource that points to a given node over the + * specified arc & truth value + */ + NS_IMETHOD GetSource(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFNode*& source /* out */) = 0; - NS_IMETHOD GetResource(RDF_String id, - RDF_Resource * r) = 0; + /** + * Find all RDF resources that point to a given node over the + * specified arc & truth value + */ + NS_IMETHOD GetSources(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFCursor*& sources /* out */) = 0; - NS_IMETHOD CreateResource(RDF_String id, - RDF_Resource* r) = 0; + /** + * Find a child of that is related to the source by the given arc + * arc and truth value + */ + NS_IMETHOD GetTarget(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFNode*& target /* out */) = 0; - NS_IMETHOD ReleaseResource(RDF_Resource r) = 0; + /** + * Find all children of that are related to the source by the given arc + * arc and truth value + */ + NS_IMETHOD GetTargets(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFCursor*& targets /* out */) = 0; - /** - * Get the name of this data source. - * - * For regular data sources, this will be the URL of the source. - * - * For aggregated sources, it generally will not be a valid RDF URL. - */ - NS_IMETHOD GetName(const RDF_String* name /* out */ ) = 0; + /** + * Add an assertion to the graph. + */ + NS_IMETHOD Assert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv = PR_TRUE) = 0; - /** - * Find an RDF resource that points to a given node over the - * specified arc & truth value (defaults to "PR_TRUE"). - */ - NS_IMETHOD GetSource(RDF_Node target, - RDF_Resource arcLabel, - RDF_Resource *source /* out */) = 0; + /** + * Remove an assertion from the graph. + */ + NS_IMETHOD Unassert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target) = 0; - NS_IMETHOD GetSource(RDF_Node target, - RDF_Resource arcLabel, - PRBool tv, - RDF_Resource *source /* out */) = 0; + /** + * Query whether an assertion exists in this graph. + * + */ + NS_IMETHOD HasAssertion(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + PRBool& hasAssertion /* out */) = 0; - /** - * Find all RDF resources that point to a given node over the - * specified arc & truth value (defaults to "PR_TRUE"). - */ - NS_IMETHOD GetSources(RDF_Resource target, - RDF_Resource arcLabel, - nsIRDFCursor **sources /* out */) = 0; + /** + * Add an observer to this data source. + */ + NS_IMETHOD AddObserver(nsIRDFObserver* n) = 0; - NS_IMETHOD GetSources(RDF_Resource target, - RDF_Resource arcLabel, - PRBool tv, - nsIRDFCursor **sources /* out */) = 0; + /** + * Remove an observer from this data source + */ + NS_IMETHOD RemoveObserver(nsIRDFObserver* n) = 0; - /** - * Find a child of that is related to the source by the given arc - * arc and truth value (defaults to PR_TRUE). - */ - NS_IMETHOD GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - RDF_NodeStruct& target /* in/out */) = 0; + // XXX individual resource observers? - NS_IMETHOD GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - PRBool tv, - RDF_NodeStruct& target /* in/out */) = 0; + /** + * Get a cursor to iterate over all the arcs that point into a node. + */ + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, + nsIRDFCursor*& labels /* out */) = 0; - /** - * Find all children of that are related to the source by the given arc - * arc and truth value (defaults to PR_TRUE). - */ - NS_IMETHOD GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */) = 0; + /** + * Get a cursor to iterate over all the arcs that originate in + * a resource. + */ + NS_IMETHOD ArcLabelsOut(nsIRDFNode* source, + nsIRDFCursor*& labels /* out */) = 0; - NS_IMETHOD GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - PRBool tv, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */) = 0; - -#ifdef RDF_NOT_IMPLEMENTED - /** - * Find all parents that point to a node over a given arc label, - * regardless of truth value. - */ - NS_IMETHOD GetAllSources(RDF_Node target, - RDF_Resource arcLabel, - nsIRDFCursor2 **sources /* out */) = 0; - - /** - * Find all children of a resource that are related by the - * given arc label, regardless of the truth value. - */ - NS_IMETHOD GetAllTargets(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - nsIRDFCursor2 **targets /* out */); -#endif /* RDF_NOT_IMPLEMENTED */ - - - /** - * Add an assertion to the graph. - */ - NS_IMETHOD Assert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool tv = PR_TRUE) = 0; - - /** - * Remove an assertion from the graph. - */ - NS_IMETHOD Unassert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target) = 0; - - /** - * Query whether an assertion exists in this graph. - * - */ - NS_IMETHOD HasAssertion(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool truthValue, - PRBool* hasAssertion /* out */) = 0; - - /** - * Add an observer to this data source. - */ - NS_IMETHOD AddObserver(nsIRDFObserver *n, - RDF_EventMask type = RDF_ANY_NOTIFY) = 0; - - /** - * Remove an observer from this data source - */ - NS_IMETHOD RemoveObserver(nsIRDFObserver *n, - RDF_EventMask = RDF_ANY_NOTIFY) = 0; - - /** - * Get a cursor to iterate over all the arcs that point into a node. - */ - NS_IMETHOD ArcLabelsIn(RDF_Node node, - nsIRDFCursor **labels /* out */) = 0; - - /** - * Get a cursor to iterate over all the arcs that originate in - * a resource. - */ - NS_IMETHOD ArcLabelsOut(RDF_Resource source, - nsIRDFCursor **labels /* out */) = 0; - -#ifdef RDF_NOT_IMPLEMENTED - /** - * Notify this data source that it is a child of a database. - * - * The datasource must send notifications to the parent when - * changes to it's graph are made, in case the parent has observers - * interested in the events generated. - */ - NS_IMETHOD AddParent(nsIRDFDataBase* parent) = 0; - - /** - * Notify this data source that it has been disconnected from a - * parent. - */ - NS_IMETHOD RemoveParent(nsIRDFDataBase* parent) = 0; - - /** - * Request that a data source obtain updates if applicable. - */ - // XXX move this to an nsIRDFRemoteDataStore interface? - NS_IMETHOD Update(RDF_Resource hint) = 0; -#endif /* RDF_NOT_IMPLEMENTED */ - - /** - * Request that a data source write it's contents out to - * permanent storage if applicable. - */ - NS_IMETHOD Flush() = 0; + /** + * Request that a data source write it's contents out to + * permanent storage if applicable. + */ + NS_IMETHOD Flush() = 0; }; diff --git a/rdf/include/nsIRDFNode.h b/rdf/include/nsIRDFNode.h new file mode 100644 index 000000000000..2399edb813dd --- /dev/null +++ b/rdf/include/nsIRDFNode.h @@ -0,0 +1,66 @@ +/* -*- 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. + */ + +#ifndef nsIRDFNode_h__ +#define nsIRDFNode_h__ + +#include "nsISupports.h" + +class nsString; +class nsIAtom; + +// {0F78DA50-8321-11d2-8EAC-00805F29F370} +#define NS_IRDFNODE_IID \ +{ 0xf78da50, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + +/** + A globally unique node in the RDF graph that can be compared + for equality using "==". Nodes are created using an instance of + nsIRDFResourceManager, which should be obtained from the service + manager: + + nsIRDFResourceManager* mgr; + if (NS_SUCCEEDED(nsServiceManager::GetService(kCRDFResourceManagerCID, + kIRDFResourceManagerIID, + &mgr))) { + nsIRDFNode* node; + if (NS_SUCCEEDED(mgr->GetNode(nsString("http://foo.bar/"), node))) { + // do something useful here... + NS_IF_RELEASE(node); + } + nsServiceManager::ReleaseService(kCRDFManagerCID, mgr); + } + + */ + +class nsIRDFNode : public nsISupports { +public: + /** + * Get the string value of the node. + */ + NS_IMETHOD GetStringValue(nsString& value) const = 0; + + /** + * Get the string value of the node as an atom + */ + NS_IMETHOD GetAtomValue(nsIAtom*& value) const = 0; +}; + + + +#endif // nsIRDFNode_h__ diff --git a/rdf/include/nsIRDFObserver.h b/rdf/include/nsIRDFObserver.h index 69703ba23836..718e937c24bf 100644 --- a/rdf/include/nsIRDFObserver.h +++ b/rdf/include/nsIRDFObserver.h @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- 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 @@ -41,10 +41,7 @@ class nsIRDFDataSource; class nsIRDFObserver : public nsISupports { public: - - NS_IMETHOD HandleEvent(nsIRDFDataSource *source, - RDF_Event event) = 0; - + }; diff --git a/rdf/include/nsIRDFRegistry.h b/rdf/include/nsIRDFRegistry.h new file mode 100644 index 000000000000..b611e71dbf29 --- /dev/null +++ b/rdf/include/nsIRDFRegistry.h @@ -0,0 +1,57 @@ +/* -*- 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. + */ + +#ifndef nsIRDFRegistry_h__ +#define nsIRDFRegistry_h__ + +#include "nsISupports.h" +class nsString; +class nsIRDFDataSource; + +// {E638D762-8687-11d2-B530-000000000000} +#define NS_IRDFREGISTRY_IID \ +{ 0xe638d762, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +/** + * The RDF registry manages the RDF data sources. + */ +class nsIRDFRegistry : public nsISupports { +public: + /** + * Registers the specified prefix as being handled by the + * data source. Note that the data source will not + * be reference counted. + */ + NS_IMETHOD Register(const nsString& prefix, nsIRDFDataSource* dataSource) = 0; + + /** + * Unregisters the data source from the registry. + */ + NS_IMETHOD Unregister(const nsIRDFDataSource* dataSource) = 0; + + /** + * Looks for a data source that will handle the specified URI. + */ + NS_IMETHOD Find(const nsString& uri, nsIRDFDataSource*& result) = 0; +}; + + +#endif nsIRDFRegistry_h__ + + + diff --git a/rdf/include/nsIRDFResourceManager.h b/rdf/include/nsIRDFResourceManager.h new file mode 100644 index 000000000000..d6a108d9160a --- /dev/null +++ b/rdf/include/nsIRDFResourceManager.h @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +#ifndef nsIRDFResourceManager_h__ +#define nsIRDFResourceManager_h__ + +#include "nsISupports.h" +class nsString; +class nsIRDFNode; + +// {BFD05261-834C-11d2-8EAC-00805F29F370} +#define NS_IRDFRESOURCEMANAGER_IID \ +{ 0xbfd05261, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + + +class nsIRDFResourceManager : public nsISupports { +public: + NS_IMETHOD GetNode(const nsString& uri, nsIRDFNode*& resource) = 0; +}; + + +#endif // nsIRDFResourceManager_h__ diff --git a/rdf/include/nsRDFCID.h b/rdf/include/nsRDFCID.h index 3ba1f54e5a57..72c1044c9f52 100644 --- a/rdf/include/nsRDFCID.h +++ b/rdf/include/nsRDFCID.h @@ -19,13 +19,34 @@ #ifndef nsRDFCID_h__ #define nsRDFCID_h__ -// {2564E6E0-79C9-11d2-B51D-000000000000} -#define NS_RDFTREEDATAMODEL_CID \ -{ 0x2564e6e0, 0x79c9, 0x11d2, { 0xb5, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } +// {0F78DA56-8321-11d2-8EAC-00805F29F370} +#define NS_RDFNODE_CID \ +{ 0xf78da56, 0x8321, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + +// {BFD05264-834C-11d2-8EAC-00805F29F370} +#define NS_RDFRESOURCEMANAGER_CID \ +{ 0xbfd05264, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + +// {BFD0526D-834C-11d2-8EAC-00805F29F370} +#define NS_RDFMEMORYDATASOURCE_CID \ +{ 0xbfd0526d, 0x834c, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + +// {E638D760-8687-11d2-B530-000000000000} +#define NS_RDFBOOKMARKDATASOURCE_CID \ +{ 0xe638d760, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +// {E638D761-8687-11d2-B530-000000000000} +#define NS_RDFSIMPLEDATABASE_CID \ +{ 0xe638d761, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +// {E638D763-8687-11d2-B530-000000000000} +#define NS_RDFREGISTRY_CID \ +{ 0xe638d763, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +// {954F0813-81DC-11d2-B52A-000000000000} +#define NS_RDFDOCUMENT_CID \ +{ 0x954f0813, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } -// {6B13A9C0-79C9-11d2-B51D-000000000000} -#define NS_RDFTOOLBARDATAMODEL_CID \ -{ 0x6b13a9c0, 0x79c9, 0x11d2, { 0xb5, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } #endif // nsRDFCID_h__ diff --git a/rdf/include/rdf.h b/rdf/include/rdf.h index f53aa0914766..f3d6c58f16b6 100644 --- a/rdf/include/rdf.h +++ b/rdf/include/rdf.h @@ -23,6 +23,26 @@ #include "nspr.h" #include "nsError.h" +/* + * The following macros are to aid in vocabulary definition. + * They creates const char*'s for "kURI[prefix]_[name]" and + * "kTag[prefix]_[name]", with appropriate complete namespace + * qualification on the URI, e.g., + * + * #define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#" + * DEFINE_RDF_ELEMENT(RDF_NAMESPACE_URI, RDF, ID); + * + * will define: + * + * kURIRDF_ID to be "http://www.w3.org/TR/WD-rdf-syntax#ID", and + * kTagRDF_ID to be "ID" + */ + +#define DEFINE_RDF_VOCAB(namespace, prefix, name) \ +static const char kURI##prefix##_##name [] = ##namespace #name ;\ +static const char* kTag##prefix##_##name = kURI##prefix##_##name## + sizeof(##namespace) - 1 + + typedef int RDF_Error; #define RDF_ERROR_ILLEGAL_ASSERT 1 /* NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_RDF,1) */ @@ -58,17 +78,6 @@ typedef struct RDF_BlobStruct { } *RDF_Blob; #endif -typedef struct RDF_NodeStruct { - RDF_ValueType type; - union { - RDF_Resource r; - RDF_String s; -#ifdef RDF_BLOB - RDF_Blob b; -#endif - } value; -} *RDF_Node; - typedef PRUint32 RDF_EventType; #define RDF_ASSERT_NOTIFY ((RDF_EventType)0x00000001) #define RDF_DELETE_NOTIFY ((RDF_EventType)0x00000002) diff --git a/rdf/src/comwrap.cpp b/rdf/src/comwrap.cpp deleted file mode 100644 index 2588f4942b9f..000000000000 --- a/rdf/src/comwrap.cpp +++ /dev/null @@ -1,712 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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 "rdf.h" - -#include "nspr.h" -#include "plhash.h" - -PR_BEGIN_EXTERN_C -PR_PUBLIC_API(void) _comwrap_NotificationCB(RDF_Event event, void* pdata); -PR_END_EXTERN_C - -class rdfDataBaseWrapper; -class rdfCursorWrapper; -class rdfServiceWrapper; -class rdfServiceFactory; - -static nsIRDFService* gRDFServiceSingleton = 0; - -class rdfDatabaseWrapper : public nsIRDFDataBase { -public: - NS_DECL_ISUPPORTS - - rdfDatabaseWrapper(RDF r); - virtual ~rdfDatabaseWrapper(); - - /* nsIRDFDataSource methods: */ - - NS_METHOD GetResource(RDF_String id, - RDF_Resource * r); - - NS_METHOD CreateResource(RDF_String id, - RDF_Resource* r); - - NS_METHOD ReleaseResource(RDF_Resource r); - - NS_METHOD GetName(const RDF_String* name /* out */ ); - - NS_METHOD GetSource(RDF_Node target, - RDF_Resource arcLabel, - RDF_Resource *source /* out */); - - NS_METHOD GetSource(RDF_Node target, - RDF_Resource arcLabel, - PRBool tv, - RDF_Resource *source /* out */); - - NS_METHOD GetSources(RDF_Resource target, - RDF_Resource arcLabel, - nsIRDFCursor **sources /* out */); - - NS_METHOD GetSources(RDF_Resource target, - RDF_Resource arcLabel, - PRBool tv, - nsIRDFCursor **sources /* out */); - - NS_METHOD GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - RDF_NodeStruct& target /* in/out */); - - NS_METHOD GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - PRBool tv, - RDF_NodeStruct& target /* in/out */); - - NS_METHOD GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */); - - NS_METHOD GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - PRBool tv, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */); - - NS_METHOD Assert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool tv = PR_TRUE); - - NS_METHOD Unassert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target); - - NS_METHOD HasAssertion(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool tv, - PRBool* hasAssertion /* out */); - - NS_METHOD AddObserver(nsIRDFObserver *n, - RDF_EventMask type = RDF_ANY_NOTIFY); - - NS_METHOD RemoveObserver(nsIRDFObserver *n, - RDF_EventMask = RDF_ANY_NOTIFY); - - NS_METHOD ArcLabelsIn(RDF_Node node, - nsIRDFCursor **labels /* out */); - - NS_METHOD ArcLabelsOut(RDF_Resource source, - nsIRDFCursor **labels /* out */); - - NS_METHOD Flush(); - - /* nsIRDFDataBase methods: */ - NS_METHOD AddDataSource(nsIRDFDataSource* dataSource); - - NS_METHOD RemoveDataSource(nsIRDFDataSource* dataSource); - - NS_METHOD GetDataSource(RDF_String url, - nsIRDFDataSource **source /* out */ ); - - NS_METHOD DeleteAllArcs(RDF_Resource resource); - -private: - RDF mRDF; - - PLHashTable* mpObserverMap; -}; - -class rdfCursorWrapper : public nsIRDFCursor { -public: - NS_DECL_ISUPPORTS - - rdfCursorWrapper(RDF_Cursor c); - virtual ~rdfCursorWrapper(); - - NS_METHOD HasElements(PRBool& hasElements); - - NS_METHOD Next(RDF_NodeStruct& n); - -private: - RDF_Cursor mCursor; - PRBool mHasCached; - RDF_NodeStruct mNextValue; -}; - -class rdfServiceWrapper : public nsIRDFService { -public: - NS_DECL_ISUPPORTS - - rdfServiceWrapper(); - virtual ~rdfServiceWrapper(); - - NS_METHOD CreateDatabase(const char** url, - nsIRDFDataBase** db); - - NS_METHOD ResourceIdentifier(RDF_Resource r, - char** url /* out */); -#ifdef MOZILLA_CLIENT - NS_METHOD SetBookmarkFile(const char* bookmarkFilePath); -#endif -}; - - - -class rdfServiceFactory : public nsIFactory { -public: - NS_DECL_ISUPPORTS - - rdfServiceFactory(); - virtual ~rdfServiceFactory(); - - NS_METHOD CreateInstance(nsISupports *aOuter, - REFNSIID anIID, - void **aResult); - - NS_METHOD LockFactory(PRBool aLock); - -}; - -/* - - rdfDataBaseWrapper: - -*/ - -static NS_DEFINE_IID(kIRDFDataBaseIID, NS_IRDFDATABASE_IID); -NS_IMPL_ISUPPORTS( rdfDatabaseWrapper, kIRDFDataBaseIID ) - -rdfDatabaseWrapper::rdfDatabaseWrapper(RDF r) : mRDF(r) -{ - mpObserverMap = PL_NewHashTable( 100, - NULL, // XXX isn't there are hash fn for pointers??? - PL_CompareValues, - PL_CompareValues, - 0, - 0 ); - - PR_ASSERT( mpObserverMap ); -#ifdef XXX - if( !mpObserverMap ) // XXX just like 'new' failing on this object? - throw bad_alloc("rdf: unable to allocate observer map" ); -#endif - -} - -rdfDatabaseWrapper::~rdfDatabaseWrapper() -{ - PL_HashTableDestroy( mpObserverMap ); -} - -NS_METHOD -rdfDatabaseWrapper::GetResource(RDF_String id, - RDF_Resource * r) -{ - PR_ASSERT( 0 != r ); - if( 0 == r ) - return NS_ERROR_NULL_POINTER; - - *r = 0; - - *r = RDF_GetResource( mRDF, id, PR_FALSE ); - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::CreateResource(RDF_String id, - RDF_Resource* r) -{ - PR_ASSERT( 0 != r ); - if( 0 == r ) - return NS_ERROR_NULL_POINTER; - - *r = 0; - - *r = RDF_GetResource( mRDF, id, PR_TRUE ); - if( 0 == *r ) { // XXX - PR_ASSERT( PR_FALSE ); - return NS_ERROR_BASE; - } - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::ReleaseResource(RDF_Resource r) -{ - RDF_ReleaseResource( mRDF, r ); - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::GetName(const RDF_String* name /* out */ ) -{ - PR_ASSERT( PR_FALSE ); - return NS_ERROR_NOT_IMPLEMENTED; // XXX -} - -NS_METHOD -rdfDatabaseWrapper::GetSource(RDF_Node target, - RDF_Resource arcLabel, - RDF_Resource *source /* out */) -{ - PR_ASSERT( target && source ); - *source = (RDF_Resource) RDF_GetSlotValue( mRDF, - target->value.r, - arcLabel, - RDF_RESOURCE_TYPE, // anything else makes no sense - PR_TRUE, - PR_TRUE ); - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::GetSource(RDF_Node target, - RDF_Resource arcLabel, - PRBool tv, - RDF_Resource *source /* out */) -{ - *source = (RDF_Resource) RDF_GetSlotValue( mRDF, - target->value.r, - arcLabel, - RDF_RESOURCE_TYPE, // anything else makes no sense - PR_TRUE, - tv ); - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::GetSources(RDF_Resource target, - RDF_Resource arcLabel, - nsIRDFCursor **sources /* out */) -{ - return GetSources(target,arcLabel,PR_TRUE,sources); -} - -NS_METHOD -rdfDatabaseWrapper::GetSources(RDF_Resource target, - RDF_Resource arcLabel, - PRBool tv, - nsIRDFCursor **sources /* out */) -{ - PR_ASSERT( sources ); - if( 0 == sources ) - return NS_ERROR_NULL_POINTER; - - *sources = 0; - - RDF_Cursor c = RDF_GetSources( mRDF, - target, - arcLabel, - RDF_RESOURCE_TYPE, // anything else makes no sense - tv ); - - if( c ) { - *sources = new rdfCursorWrapper( c ); - (*sources)->AddRef(); - } - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - RDF_NodeStruct& target /* in/out */) -{ - return GetTarget(source,arcLabel,targetType,PR_TRUE,target); -} - -NS_METHOD -rdfDatabaseWrapper::GetTarget(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - PRBool tv, - RDF_NodeStruct& target /* in/out */) -{ - PR_ASSERT( targetType != RDF_ANY_TYPE ); // not ready to support this yet - - void* value = RDF_GetSlotValue( mRDF, - target.value.r, - arcLabel, - targetType, // anything else makes no sense - PR_FALSE, - tv ); - - target.type = targetType; - target.value.r = (RDF_Resource) value; // reasonable? XXX - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */) -{ - return GetTargets(source,arcLabel,PR_TRUE,targetType,targets); -} - -NS_METHOD -rdfDatabaseWrapper::GetTargets(RDF_Resource source, - RDF_Resource arcLabel, - PRBool tv, - RDF_ValueType targetType, - nsIRDFCursor **targets /* out */) -{ - PR_ASSERT( targets ); - if( 0 == targets ) - return NS_ERROR_NULL_POINTER; - - *targets = 0; - - RDF_Cursor c = RDF_GetTargets( mRDF, - source, - arcLabel, - targetType, - tv ); - - if( c ) { - *targets = new rdfCursorWrapper( c ); - (*targets)->AddRef(); - } - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::Assert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool tv) -{ - PRBool b = tv ? RDF_Assert( mRDF, source, arcLabel, (void*)target->value.r, target->type ) : - RDF_AssertFalse( mRDF, source, arcLabel, (void*)target->value.r, target->type ); - - // XXX - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::Unassert(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target) -{ - PRBool b = RDF_Unassert( mRDF, - source, - arcLabel, - target->value.r, - target->type ); // XXX - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::HasAssertion(RDF_Resource source, - RDF_Resource arcLabel, - RDF_Node target, - PRBool truthValue, - PRBool* hasAssertion /* out */) -{ - *hasAssertion = RDF_HasAssertion( mRDF, - source, - arcLabel, - target->value.r, - target->type, - truthValue ); - - return NS_OK; -} - -PR_IMPLEMENT(void) - _comwrap_NotificationCB(RDF_Event event, void* pdata) -{ - nsIRDFObserver* observer = (nsIRDFObserver*) pdata; - // XXX QueryInterface & release?? - observer->HandleEvent( (nsIRDFDataSource*)pdata, event ); -} - -NS_METHOD -rdfDatabaseWrapper::AddObserver(nsIRDFObserver *observer, - RDF_EventMask type) -{ - // XXX event masking does not currently work - - RDF_Notification notification = (RDF_Notification) PL_HashTableLookup( mpObserverMap, observer ); - if( !notification ) { - observer->AddRef(); - notification = RDF_AddNotifiable( mRDF, - _comwrap_NotificationCB, - NULL, // XXX - observer ); - PL_HashTableAdd( mpObserverMap, - observer, - notification ); - } - - return NS_OK; // XXX -} - -NS_METHOD -rdfDatabaseWrapper::RemoveObserver(nsIRDFObserver *observer, - RDF_EventMask type) -{ - - RDF_Notification notification = (RDF_Notification) PL_HashTableLookup( mpObserverMap, observer ); - if( !notification ) - return NS_ERROR_ILLEGAL_VALUE; - - RDF_Error err = RDF_DeleteNotifiable( notification ); - PR_ASSERT( !err ); // the current implementation never fails! - PL_HashTableRemove( mpObserverMap, observer ); - observer->Release(); - - return NS_OK; // XXX -} - -NS_METHOD -rdfDatabaseWrapper::ArcLabelsIn(RDF_Node node, - nsIRDFCursor **labels /* out */) -{ - PR_ASSERT( labels ); - if( 0 == labels ) - return NS_ERROR_NULL_POINTER; - *labels = 0; - - RDF_Cursor c = RDF_ArcLabelsIn( mRDF, node->value.r ); - - if( c ) { - *labels = new rdfCursorWrapper( c ); - (*labels)->AddRef(); - } - - return NS_OK; - -} - -NS_METHOD -rdfDatabaseWrapper::ArcLabelsOut(RDF_Resource source, - nsIRDFCursor **labels /* out */) -{ - PR_ASSERT( labels ); - if( 0 == labels ) - return NS_ERROR_NULL_POINTER; - *labels = 0; - - RDF_Cursor c = RDF_ArcLabelsOut( mRDF, source ); - - if( c ) { - *labels = new rdfCursorWrapper( c ); - (*labels)->AddRef(); - } - - return NS_OK; -} - -NS_METHOD -rdfDatabaseWrapper::Flush() -{ - return NS_ERROR_NOT_IMPLEMENTED; // XXX -} - - -NS_METHOD -rdfDatabaseWrapper::DeleteAllArcs(RDF_Resource resource) -{ - return RDF_DeleteAllArcs( mRDF, resource ); -} - -/* - - rdfServiceWrapper: the RDF service singleton - -*/ - -static NS_DEFINE_IID(kIRDFServiceIID, NS_IRDFSERVICE_IID); -NS_IMPL_ISUPPORTS(rdfServiceWrapper, kIRDFServiceIID ) - -rdfServiceWrapper::rdfServiceWrapper() -{ - nsresult err = RDF_Init(); // this method currently cannot fail - PR_ASSERT( err == NS_OK ); // XXX -} - -rdfServiceWrapper::~rdfServiceWrapper() -{ - nsresult err = RDF_Shutdown(); // this method currently cannot fail - PR_ASSERT( err == NS_OK ); // XXX -} - -NS_METHOD -rdfServiceWrapper::CreateDatabase(const char** url_ary, - nsIRDFDataBase **db) -{ - PR_ASSERT( 0 != db ); - if( 0 == db ) - return NS_ERROR_NULL_POINTER; - - *db = 0; - - nsresult result = NS_OK; - RDF rdf = RDF_GetDB(url_ary); - - if( 0 == rdf ) { - result = RDF_ERROR_UNABLE_TO_CREATE; // XXX this is too wishy-washy - } else { - *db = new rdfDatabaseWrapper(rdf); // XXX - } - - return result; -} - -NS_METHOD -rdfServiceWrapper::ResourceIdentifier(RDF_Resource r, - char** url) -{ - char* resourceID(RDF_Resource r); - PR_ASSERT( 0 != r ); - if( 0 == r ) - return NS_ERROR_NULL_POINTER; - *url = RDF_ResourceID(r); - return NS_OK; -} - -#ifdef MOZILLA_CLIENT -NS_METHOD -rdfServiceWrapper::SetBookmarkFile(const char* bookmarkFilePath) { - SetBookmarkURL(bookmarkFilePath); - return NS_OK; -} -#endif - - -/* - - rdfCursorWrapper - -*/ - -static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID); -NS_IMPL_ISUPPORTS( rdfCursorWrapper, kIRDFCursorIID ) - -rdfCursorWrapper::rdfCursorWrapper(RDF_Cursor c) : mCursor(c) -{ - mHasCached = PR_FALSE; -} - -rdfCursorWrapper::~rdfCursorWrapper() -{ - RDF_DisposeCursor( mCursor ); -} - -NS_METHOD -rdfCursorWrapper::HasElements(PRBool& hasElements) -{ - mNextValue.type = RDF_CursorValueType( mCursor ); - mNextValue.value.r = (RDF_Resource) RDF_NextValue( mCursor ); - - if( mNextValue.value.r != NULL ) { - hasElements = PR_FALSE; - mHasCached = PR_TRUE; - } else { - hasElements = PR_TRUE; - mHasCached = PR_FALSE; - } - - return NS_OK; -} - -NS_METHOD -rdfCursorWrapper::Next(RDF_NodeStruct& next) -{ - if( mHasCached == PR_TRUE ) { - next.type = mNextValue.type; - next.value.r = mNextValue.value.r; - mHasCached = PR_FALSE; - } else { - next.type = RDF_CursorValueType( mCursor ); - next.value.r = (RDF_Resource) RDF_NextValue( mCursor ); - } - - return NS_OK; -} - -/* - - rdfServiceFactory - -*/ - -static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); -NS_IMPL_ISUPPORTS( rdfServiceFactory, kIFactoryIID ) - -NS_METHOD -rdfServiceFactory::CreateInstance( nsISupports *aOuter, - REFNSIID aIID, - void **aResult ) -{ - PR_ASSERT( aResult ); - if( 0 == aResult ) - return NS_ERROR_NULL_POINTER; - *aResult = 0; - - nsISupports* instance = new rdfServiceWrapper(); - - nsresult result = instance->QueryInterface( aIID, aResult ); - PR_ASSERT( result = NS_OK ); - - if( result != NS_OK ) - delete instance; // wrong interface! - - return result; -} - -NS_METHOD -rdfServiceFactory::LockFactory(PRBool lock) -{ - PR_ASSERT( PR_FALSE ); - return NS_ERROR_NOT_IMPLEMENTED; -} - -PR_IMPLEMENT(nsresult) -NS_GetRDFService(nsIRDFService **s) -{ - PR_ASSERT( s ); - if( 0 == s ) - return NS_ERROR_NULL_POINTER; - - *s = 0; - - if( 0 == gRDFServiceSingleton ) { - gRDFServiceSingleton = new rdfServiceWrapper(); // XXX use factory, check for errors - } - - *s = gRDFServiceSingleton; - - return NS_OK; -} diff --git a/rdf/src/makefile.win b/rdf/src/makefile.win index 546ad1c075a8..3f79fcbbd4ca 100644 --- a/rdf/src/makefile.win +++ b/rdf/src/makefile.win @@ -15,7 +15,6 @@ # Copyright (C) 1998 Netscape Communications Corporation. All Rights # Reserved. - DEPTH = ..\.. MODULE=rdf @@ -24,31 +23,44 @@ DLLNAME=rdf DLL=.\$(OBJDIR)\$(DLLNAME).dll -C_OBJS=\ - .\$(OBJDIR)\vocab.obj \ - .\$(OBJDIR)\core.obj \ - .\$(OBJDIR)\remstore.obj \ - .\$(OBJDIR)\utils.obj \ - .\$(OBJDIR)\rdfparse.obj \ - .\$(OBJDIR)\bmk2rdf.obj \ - .\$(OBJDIR)\columns.obj \ - .\$(OBJDIR)\rdfht.obj \ - $(NULL) - CPP_OBJS=\ - .\$(OBJDIR)\comwrap.obj \ - .\$(OBJDIR)\netglue.obj \ - .\$(OBJDIR)\nsRDFDataModel.obj \ - .\$(OBJDIR)\nsRDFDataModelItem.obj \ + .\$(OBJDIR)\nsBookmarkDataSource.obj \ + .\$(OBJDIR)\nsEmptyCursor.obj \ + .\$(OBJDIR)\nsMemoryDataSource.obj \ + .\$(OBJDIR)\nsRDFContentSink.obj \ + .\$(OBJDIR)\nsRDFDocument.obj \ + .\$(OBJDIR)\nsRDFElement.obj \ .\$(OBJDIR)\nsRDFFactory.obj \ - .\$(OBJDIR)\nsRDFToolbarDataModel.obj \ - .\$(OBJDIR)\nsRDFToolbarDataModelItem.obj \ - .\$(OBJDIR)\nsRDFTreeColumn.obj \ - .\$(OBJDIR)\nsRDFTreeDataModel.obj \ - .\$(OBJDIR)\nsRDFTreeDataModelItem.obj \ + .\$(OBJDIR)\nsRDFRegistryImpl.obj \ + .\$(OBJDIR)\nsRDFResourceManager.obj \ + .\$(OBJDIR)\nsSimpleDataBase.obj \ $(NULL) +# Right now, the RDF parser depends on some of the Raptor support +# classes to work (e.g., nsDocument). So, we need to reach over +# and link in a bunch of private stuff from over there. This *will* +# go away. +EVIL_RAPTOR_DEPENDENCY=1 + LLIBS=\ +!ifdef EVIL_RAPTOR_DEPENDENCY + $(DIST)\lib\raptorhtml.lib \ + $(DIST)\lib\raptorlayout_s.lib \ + $(DIST)\lib\raptorhtmlbase_s.lib \ + $(DIST)\lib\nglhtmlcon_s.lib \ + $(DIST)\lib\raptorhtmldoc_s.lib \ + $(DIST)\lib\raptorhtmlforms_s.lib \ + $(DIST)\lib\raptorhtmlstyle_s.lib \ + $(DIST)\lib\raptorhtmltable_s.lib \ + $(DIST)\lib\raptorxmlcontent_s.lib \ + $(DIST)\lib\raptorxmldoc_s.lib \ + $(DIST)\lib\raptorevents_s.lib \ + $(DIST)\lib\raptorbase.lib \ + $(DIST)\lib\raptorgfxwin.lib \ + $(DIST)\lib\raptorhtmlpars.lib \ + $(DIST)\lib\jsdom.lib \ + $(DIST)\lib\js32$(VERSION_NUMBER).lib \ +!endif $(DIST)\lib\xpcom32.lib \ $(DIST)\lib\raptorbase.lib \ $(DIST)\lib\netlib.lib \ @@ -56,9 +68,17 @@ LLIBS=\ $(LIBNSPR) LINCS= -I$(PUBLIC)\rdf \ - -I$(XPDIST)\public\xpcom \ + -I$(PUBLIC)\xpcom \ -I$(PUBLIC)\netlib \ -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\js \ + -I$(PUBLIC)\dom \ +!ifdef EVIL_RAPTOR_DEPENDENCY + -I..\..\layout\base\src \ + -I..\..\layout\html\base\src \ + -I..\..\layout\html\style\src \ + -I..\..\layout\html\document\src \ +!endif $(NULL) include <$(DEPTH)\config\rules.mak> diff --git a/rdf/src/nsBookmarkDataSource.cpp b/rdf/src/nsBookmarkDataSource.cpp new file mode 100644 index 000000000000..0a1db0163360 --- /dev/null +++ b/rdf/src/nsBookmarkDataSource.cpp @@ -0,0 +1,584 @@ +/* -*- 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 "nsIRDFDataSource.h" +#include "nsIRDFNode.h" +#include "nsIRDFResourceManager.h" +#include "nsIServiceManager.h" +#include "nsBookmarkDataSource.h" +#include "nsRDFCID.h" +#include "nsString.h" +#include "nsVoidArray.h" +#include "prio.h" +#include "rdf.h" + +//////////////////////////////////////////////////////////////////////// + +static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID); +static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID); + +static const char kURI_bookmarks[] = "rdf:bookmarks"; // XXX? + +#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#" +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Bookmark); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Folder); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Name); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, PersonalToolbarFolderCategory); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, BookmarkAddDate); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Description); + + +#define WEB_NAMESPACE_URI "http://home.netscape.com/WEB-rdf#" +DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastVisitDate); +DEFINE_RDF_VOCAB(WEB_NAMESPACE_URI, WEB, LastModifiedDate); + + +#define RDF_NAMESPACE_URI "http://www.w3.org/TR/WD-rdf-syntax#" +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf); + +static const char kPersonalToolbar[] = "Personal Toolbar"; + + +//////////////////////////////////////////////////////////////////////// + + +class BookmarkParser { +protected: + static const PRUnichar* kBRString; + static const PRUnichar* kCloseDLString; + static const PRUnichar* kDDString; + static const PRUnichar* kOpenAnchorString; + static const PRUnichar* kOpenDLString; + static const PRUnichar* kOpenH3String; + static const PRUnichar* kOpenTitleString; + static const PRUnichar* kSeparatorString; + + enum BookmarkParserState { + eBookmarkParserState_Initial, + eBookmarkParserState_InTitle, + eBookmarkParserState_InH3, + eBookmarkParserState_InItemTitle, + eBookmarkParserState_InItemDescription + }; + + nsIRDFResourceManager* mResourceMgr; + nsIRDFDataSource* mDataSource; + nsVoidArray mStack; + nsIRDFNode* mLastItem; + nsAutoString mLine; + PRInt32 mCounter; + nsAutoString mFolderDate; + BookmarkParserState mState; + + void Tokenize(const char* buf, PRInt32 size); + void NextToken(void); + void DoStateTransition(void); + void CreateBookmark(void); + + nsresult AssertTime(nsIRDFNode* subject, + const nsString& predicateURI, + const nsString& time); + + nsresult Assert(nsIRDFNode* subject, + const nsString& predicateURI, + const nsString& objectURI); + + nsresult Assert(nsIRDFNode* subject, + const nsString& predicateURI, + nsIRDFNode* object); + + nsresult Assert(nsIRDFNode* subject, + nsIRDFNode* predicate, + nsIRDFNode* object); + +public: + BookmarkParser(nsIRDFResourceManager* resourceMgr, + nsIRDFDataSource* dataSource); + + ~BookmarkParser(); + + nsresult Parse(PRFileDesc* file); +}; + + +const PRUnichar* BookmarkParser::kBRString = L"
"; +const PRUnichar* BookmarkParser::kCloseDLString = L""; +const PRUnichar* BookmarkParser::kDDString = L"
"; +const PRUnichar* BookmarkParser::kOpenAnchorString = L""; +const PRUnichar* BookmarkParser::kOpenH3String = L""; +const PRUnichar* BookmarkParser::kSeparatorString = L"
"; + + +BookmarkParser::BookmarkParser(nsIRDFResourceManager* resourceMgr, + nsIRDFDataSource* dataSource) + : mResourceMgr(resourceMgr), + mDataSource(dataSource) +{ + NS_IF_ADDREF(mResourceMgr); + //NS_IF_ADDREF(mDataSource); +} + +BookmarkParser::~BookmarkParser(void) +{ + //NS_IF_RELEASE(mDataSource); + NS_IF_RELEASE(mResourceMgr); +} + +nsresult +BookmarkParser::Parse(PRFileDesc* file) +{ + if (! file) + return NS_ERROR_NULL_POINTER; + + if (! mResourceMgr) + return NS_ERROR_NULL_POINTER; + + if (! mDataSource) + return NS_ERROR_NULL_POINTER; + + // Initialize the parser for a run... + mState = eBookmarkParserState_Initial; + mCounter = 0; + mLastItem = NULL; + mLine.Truncate(); + + nsresult rv; + nsIRDFNode* bookmarks; + if (NS_SUCCEEDED(rv = mResourceMgr->GetNode(kURI_bookmarks, bookmarks))) { + mStack.AppendElement(bookmarks); + + char buf[1024]; + PRInt32 len; + + while ((len = PR_Read(file, buf, sizeof(buf))) > 0) + Tokenize(buf, len); + + NS_RELEASE(bookmarks); + } + + NS_IF_RELEASE(mLastItem); + return rv; +} + +void +BookmarkParser::Tokenize(const char* buf, PRInt32 size) +{ + for (PRInt32 i = 0; i < size; ++i) { + char c = buf[i]; + if (c == '<') { + if (mLine.Length() > 0) { + NextToken(); + mLine.Truncate(); + } + } + mLine.Append(c); + if (c == '>') { + if (mLine.Length() > 0) { + NextToken(); + mLine.Truncate(); + } + } + } +} + + +void +BookmarkParser::NextToken(void) +{ + if (mLine[0] == '<') { + DoStateTransition(); + return; + } + + /* ok, we have a piece of content. can be the title, or a description */ + if ((mState == eBookmarkParserState_InTitle) || + (mState == eBookmarkParserState_InH3) || + (mState == eBookmarkParserState_InItemTitle)) { + // Create a new folder + nsAutoString folderURI(kURI_bookmarks); + folderURI.Append('#'); + folderURI.Append(++mCounter, 10); + + nsIRDFNode* parent = (nsIRDFNode*) mStack[mStack.Count() - 1]; + PR_ASSERT(parent); + if (! parent) + return; + + nsIRDFNode* folder; + if (NS_FAILED(mResourceMgr->GetNode(folderURI, folder))) + return; + + Assert(parent, kURINC_Folder, folder); + + if (mFolderDate.Length()) { + AssertTime(folder, kURINC_BookmarkAddDate, mFolderDate); + mFolderDate.Truncate(); + } + + NS_IF_RELEASE(mLastItem); + mLastItem = folder; + + if (mState != eBookmarkParserState_InTitle) + Assert(mLastItem, kURINC_Name, mLine); + + if (mLine.Find(kPersonalToolbar) == 0) + Assert(mLastItem, kURIRDF_instanceOf, kURINC_PersonalToolbarFolderCategory); + } + else if (mState == eBookmarkParserState_InItemDescription) { + Assert(mLastItem, kURINC_Description, mLine); + } +} + + + +void +BookmarkParser::DoStateTransition(void) +{ + if (mLine.Find(kOpenAnchorString) == 0) { + CreateBookmark(); + mState = eBookmarkParserState_InItemTitle; + } + else if (mLine.Find(kOpenH3String) == 0) { + PRInt32 start = mLine.Find('"'); + PRInt32 end = mLine.RFind('"'); + if (start >= 0 && end >= 0) + mLine.Mid(mFolderDate, start + 1, end - start - 1); + mState = eBookmarkParserState_InH3; + } + else if (mLine.Find(kOpenTitleString) == 0) { + mState = eBookmarkParserState_InTitle; + } + else if (mLine.Find(kDDString) == 0) { +#if 0 // XXX if it doesn't already have a description? Huh? + if (remoteStoreGetSlotValue(gLocalStore, mLastItem, gWebData->RDF_description, + RDF_STRING_TYPE, false, true) + == NULL) +#endif + mState = eBookmarkParserState_InItemDescription; + } + else if (mLine.Find(kOpenDLString) == 0) { + mStack.AppendElement(mLastItem); + } + else if (mLine.Find(kCloseDLString) == 0) { + PRInt32 count = mStack.Count(); + if (count) { + nsIRDFNode* top = static_cast(mStack[--count]); + mStack.RemoveElementAt(count); + NS_IF_RELEASE(top); + } + } + else if (mLine.Find(kSeparatorString) == 0) { +#if FIXME // separators + addSlotValue(f, createSeparator(), gCoreVocab->RDF_parent, mStack[mStack.Count() - 1], + RDF_RESOURCE_TYPE, NULL); +#endif + mState = eBookmarkParserState_Initial; + } + else if ((mState == eBookmarkParserState_InItemDescription) && + (mLine.Find(kBRString) == 0)) { + // XXX in the original bmk2rdf.c, we only added the + // description in the case that it wasn't set already...why? + Assert(mLastItem, kURINC_Description, mLine); + } + else { + mState = eBookmarkParserState_Initial; + } +} + + + + +void +BookmarkParser::CreateBookmark(void) +{ + enum { + eBmkAttribute_URL = 0, + eBmkAttribute_AddDate = 1, + eBmkAttribute_LastVisit = 2, + eBmkAttribute_LastModified = 3 + }; + + nsAutoString values[4]; + PRInt32 index = 0; + for (PRInt32 i = 0; i < 4; ++i) { + PRInt32 start = mLine.Find('"', index); + if (start == -1) + break; + + ++start; // past the first quote + + PRInt32 end = mLine.Find('"', start); + PR_ASSERT(end > 0); // unterminated + if (end == -1) + end = mLine.Length(); + + mLine.Mid(values[i], start, end - start); + index = end + 1; + } + + if (values[eBmkAttribute_URL].Length() == 0) + return; + + nsIRDFNode* bookmark; + if (NS_FAILED(mResourceMgr->GetNode(values[eBmkAttribute_URL], bookmark))) + return; + + if (! mStack.Count()) + return; + + nsIRDFNode* parent = (nsIRDFNode*) mStack[mStack.Count() - 1]; + if (! parent) + return; + + Assert(parent, kURINC_Bookmark, bookmark); + + if (values[eBmkAttribute_AddDate].Length() > 0) + AssertTime(bookmark, kURINC_BookmarkAddDate, values[eBmkAttribute_AddDate]); + + if (values[eBmkAttribute_LastVisit].Length() > 0) + AssertTime(bookmark, kURIWEB_LastVisitDate, values[eBmkAttribute_LastVisit]); + + if (values[eBmkAttribute_LastModified].Length() > 0) + AssertTime(bookmark, kURIWEB_LastModifiedDate, values[eBmkAttribute_LastModified]); + + NS_RELEASE(bookmark); +} + + +nsresult +BookmarkParser::AssertTime(nsIRDFNode* object, + const nsString& predicateURI, + const nsString& time) +{ + // XXX + return Assert(object, predicateURI, time); +} + +nsresult +BookmarkParser::Assert(nsIRDFNode* subject, + nsIRDFNode* predicate, + nsIRDFNode* object) +{ +#ifdef DEBUG + char buf[1024]; + nsAutoString s; + + subject->GetStringValue(s); + printf("(%s\n", s.ToCString(buf, sizeof buf)); + predicate->GetStringValue(s); + printf(" %s\n", s.ToCString(buf, sizeof buf)); + object->GetStringValue(s); + printf(" %s)\n", s.ToCString(buf, sizeof buf)); +#endif + return mDataSource->Assert(subject, predicate, object); +} + + +nsresult +BookmarkParser::Assert(nsIRDFNode* subject, + const nsString& predicateURI, + nsIRDFNode* object) +{ + nsresult rv; + nsIRDFNode* predicate; + if (NS_FAILED(rv = mResourceMgr->GetNode(predicateURI, predicate))) + return rv; + + rv = Assert(subject, predicate, object); + NS_RELEASE(predicate); + + return rv; +} + + +nsresult +BookmarkParser::Assert(nsIRDFNode* subject, + const nsString& predicateURI, + const nsString& objectURI) +{ + nsresult rv; + nsIRDFNode* object; + if (NS_FAILED(rv = mResourceMgr->GetNode(objectURI, object))) + return rv; + + rv = Assert(subject, predicateURI, object); + NS_RELEASE(object); + + return rv; +} + +//////////////////////////////////////////////////////////////////////// +// nsBookmarkDataSource + +// XXX we should get this from prefs. +const char* nsBookmarkDataSource::kBookmarksFilename = "bookmarks.html"; + +nsBookmarkDataSource::nsBookmarkDataSource(void) +{ + NS_INIT_REFCNT(); + ReadBookmarks(); // XXX do or die, eh? + Initialize(kURI_bookmarks); +} + +nsBookmarkDataSource::~nsBookmarkDataSource(void) +{ + Flush(); +} + + + +NS_IMETHODIMP +nsBookmarkDataSource::Flush(void) +{ + return WriteBookmarks(); +} + + + +nsresult +nsBookmarkDataSource::ReadBookmarks(void) +{ + nsresult rv; + nsIRDFResourceManager* mgr; + + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + BookmarkParser parser(mgr, this); + PRFileDesc* f; + + rv = NS_ERROR_FAILURE; + if ((f = PR_Open(kBookmarksFilename, PR_RDONLY, 0644))) { + rv = parser.Parse(f); + PR_Close(f); + } + + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + return rv; +} + + + +nsresult +nsBookmarkDataSource::WriteBookmarks(void) +{ + //PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +#if FIXME + +static const nsString& +rdf_NumericDate(const nsString& url) +{ + nsAutoString result; + PRInt32 len = url.Length(); + PRInt32 index = 0; + + while (index < len && url[index] < '0' && url[index] > '9') + ++index; + + if (index >= len) + return result; + + while (index < len && url[index] >= '0' && url[index] <= '9') + result.Append(url[index++]); + + result; +} + + +void +HT_WriteOutAsBookmarks1 (RDF rdf, PRFileDesc *fp, RDF_Resource u, RDF_Resource top, int indent) +{ + RDF_Cursor c = RDF_GetSources(rdf, u, gCoreVocab->RDF_parent, RDF_RESOURCE_TYPE, true); + RDF_Resource next; + char *date, *name, *url; + int loop; + + if (c == NULL) return; + if (u == top) { + name = RDF_GetResourceName(rdf, u); + ht_rjcprintf(fp, "\n", NULL); + ht_rjcprintf(fp, "\n", NULL); + + ht_rjcprintf(fp, "%s\n", (name) ? name:""); + ht_rjcprintf(fp, "

%s

\n

\n", (name) ? name:""); + } + while ((next = RDF_NextValue(c)) != NULL) { + + url = resourceID(next); + if (containerp(next) && (!startsWith("ftp:",url)) && (!startsWith("file:",url)) + && (!startsWith("IMAP:", url)) && (!startsWith("nes:", url)) + && (!startsWith("mail:", url)) && (!startsWith("cache:", url)) + && (!startsWith("ldap:", url))) { + for (loop=0; loop

", (date) ? date:""); + if (date) freeMem(date); + name = RDF_GetResourceName(rdf, next); + ht_rjcprintf(fp, "%s

\n", name); + + for (loop=0; loop

\n", NULL); + HT_WriteOutAsBookmarks1(rdf, fp, next, top, indent+1); + + for (loop=0; loop

\n", NULL); + } + else if (isSeparator(next)) { + for (loop=0; loop\n", NULL); + } + else { + char* bkAddDate = (char*)RDF_GetSlotValue(rdf, next, + gNavCenter->RDF_bookmarkAddDate, + RDF_STRING_TYPE, false, true); + + for (loop=0; loop", resourceLastModifiedDate(rdf, next)); + ht_rjcprintf(fp, "%s\n", RDF_GetResourceName(rdf, next)); + + if (resourceDescription(rdf, next) != NULL) { + ht_rjcprintf(fp, "

%s\n", resourceDescription(rdf, next)); + } + } + } + RDF_DisposeCursor(c); + if (u == top) { + ht_rjcprintf(fp, "
\n", NULL); + } +} +#endif + + + diff --git a/rdf/src/nsBookmarkDataSource.h b/rdf/src/nsBookmarkDataSource.h new file mode 100644 index 000000000000..17e7a4add2e2 --- /dev/null +++ b/rdf/src/nsBookmarkDataSource.h @@ -0,0 +1,39 @@ +/* -*- 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. + */ + + +#ifndef nsBookmarkDataSource_h__ +#define nsBookmarkDataSource_h__ + +#include "nsMemoryDataSource.h" + +class nsBookmarkDataSource : public nsMemoryDataSource { +protected: + static const char* kBookmarksFilename; + + nsresult ReadBookmarks(void); + nsresult WriteBookmarks(void); + +public: + nsBookmarkDataSource(void); + virtual ~nsBookmarkDataSource(void); + + NS_IMETHOD Flush(void); +}; + +#endif nsBookmarkDataSource_h__ diff --git a/rdf/src/nsEmptyCursor.cpp b/rdf/src/nsEmptyCursor.cpp new file mode 100644 index 000000000000..6542b823661a --- /dev/null +++ b/rdf/src/nsEmptyCursor.cpp @@ -0,0 +1,91 @@ +/* -*- 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 "nsIRDFCursor.h" + +static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +class EmptyCursorImpl : public nsIRDFCursor { +public: + EmptyCursorImpl(void); + virtual ~EmptyCursorImpl(void) {}; + + // nsISupports + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + NS_IMETHOD QueryInterface(REFNSIID iid, void** result); + + // nsIRDFCursor + NS_IMETHOD HasMoreElements(PRBool& result); + NS_IMETHOD GetNext(nsIRDFNode*& next, PRBool& tv); +}; + +nsIRDFCursor* gEmptyCursor; +static EmptyCursorImpl gEmptyCursorImpl; + +EmptyCursorImpl::EmptyCursorImpl(void) +{ + gEmptyCursor = this; +} + +NS_IMETHODIMP_(nsrefcnt) +EmptyCursorImpl::AddRef(void) +{ + return 2; +} + + +NS_IMETHODIMP_(nsrefcnt) +EmptyCursorImpl::Release(void) +{ + return 1; +} + +NS_IMETHODIMP +EmptyCursorImpl::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + if (iid.Equals(kIRDFCursorIID) || + iid.Equals(kISupportsIID)) { + *result = static_cast(this); + /* AddRef(); // not necessary */ + return NS_OK; + } + return NS_NOINTERFACE; +} + + +NS_IMETHODIMP +EmptyCursorImpl::HasMoreElements(PRBool& result) +{ + result = PR_FALSE; + return NS_OK; +} + + +NS_IMETHODIMP +EmptyCursorImpl::GetNext(nsIRDFNode*& next, PRBool& tv) +{ + next = NULL; + return NS_ERROR_UNEXPECTED; +} + + diff --git a/rdf/src/nsIRDFContent.h b/rdf/src/nsIRDFContent.h new file mode 100644 index 000000000000..38485f36fcc7 --- /dev/null +++ b/rdf/src/nsIRDFContent.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef nsIRDFContent_h___ +#define nsIRDFContent_h___ + +#include "nsISupports.h" +#include "nsIXMLContent.h" + +// {954F0810-81DC-11d2-B52A-000000000000} +#define NS_IRDFCONTENT_IID \ +{ 0x954f0810, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +/** + * RDF content extensions to nsIXMLContent + */ +class nsIRDFContent : public nsIXMLContent { +public: + NS_IMETHOD SetResource(const nsString& aURI) = 0; + NS_IMETHOD GetResource(nsString& rURI) const = 0; + + NS_IMETHOD SetProperty(const nsString& aPropertyURI, const nsString& aValue) = 0; + NS_IMETHOD GetProperty(const nsString& aPropertyURI, nsString& rValue) const = 0; +}; + + +extern nsresult +NS_NewRDFElement(nsIRDFContent** aResult); + +#endif // nsIRDFContent_h___ diff --git a/rdf/src/nsIRDFContentSink.h b/rdf/src/nsIRDFContentSink.h new file mode 100644 index 000000000000..15c018c9a74d --- /dev/null +++ b/rdf/src/nsIRDFContentSink.h @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ +#ifndef nsIRDFContentSink_h___ +#define nsIRDFContentSink_h___ + +#include "nsIXMLContentSink.h" + +class nsIDocument; +class nsIURL; +class nsIWebShell; + +// {751843E2-8309-11d2-8EAC-00805F29F370} +#define NS_IRDFCONTENTSINK_IID \ +{ 0x751843e2, 0x8309, 0x11d2, { 0x8e, 0xac, 0x0, 0x80, 0x5f, 0x29, 0xf3, 0x70 } } + +/** + * This interface represents a content sink for generic XML files. + * The goal of this sink is to deal with XML documents that do not + * have pre-built semantics, though it may also be implemented for + * cases in which semantics are hard-wired. + * + * The expectation is that the parser has already performed + * well-formedness and validity checking. + * + * XXX The expectation is that entity expansion will be done by the sink + * itself. This would require, however, that the sink has the ability + * to query the parser for entity replacement text. + * + * XXX This interface does not contain a mechanism for the sink to + * get specific schema/DTD information from the parser. This information + * may be necessary for entity expansion. It is also necessary for + * building the DOM portions that relate to the schema. + * + * XXX This interface does not deal with the presence of an external + * subset. It seems possible that this could be dealt with completely + * at the parser level. + */ + +class nsIRDFContentSink : public nsIXMLContentSink { +public: +}; + +extern nsresult NS_NewRDFContentSink(nsIRDFContentSink** aInstancePtrResult, + nsIDocument* aDoc, + nsIURL* aURL, + nsIWebShell* aWebShell); + +#endif // nsIRDFContentSink_h___ diff --git a/rdf/src/nsIRDFDocument.h b/rdf/src/nsIRDFDocument.h new file mode 100644 index 000000000000..14a9583f8687 --- /dev/null +++ b/rdf/src/nsIRDFDocument.h @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef nsIRDFDocument_h___ +#define nsIRDFDocument_h___ + +#include "nsIXMLDocument.h" + +class nsString; +class nsIRDFDataBase; +class nsIRDFDataSource; +class nsIRDFNode; + +// {954F0811-81DC-11d2-B52A-000000000000} +#define NS_IRDFDOCUMENT_IID \ +{ 0x954f0811, 0x81dc, 0x11d2, { 0xb5, 0x2a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } } + +/** + * RDF document extensions to nsIDocument + */ +class nsIRDFDocument : public nsIXMLDocument { +public: + NS_IMETHOD GetDataBase(nsIRDFDataBase*& rDataBase) = 0; + + NS_IMETHOD SetDataSource(nsIRDFDataSource* aDataSource) = 0; +}; + +#endif // nsIRDFDocument_h___ diff --git a/rdf/src/nsMemoryDataSource.cpp b/rdf/src/nsMemoryDataSource.cpp new file mode 100644 index 000000000000..dc06d0e053f9 --- /dev/null +++ b/rdf/src/nsMemoryDataSource.cpp @@ -0,0 +1,730 @@ +/* -*- 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. + */ + +/* + + Implementation for an in-memory RDF data store. + + TO DO: + + 1) There is no implementation for walking property arcs backwards; + i.e., GetSource(), GetSources(), and ArcLabelsIn(). Gotta fix + this. Or maybe factor the API so that you don't always need to + implement that crap. I can see that being a real headache for + some implementations. + + 2) Need to hook up observer mechanisms. + + */ + +#include "nsMemoryDataSource.h" +#include "nsIRDFCursor.h" +#include "nsIRDFNode.h" +#include "nsIRDFRegistry.h" +#include "nsIServiceManager.h" +#include "nsISupportsArray.h" +#include "nsRDFCID.h" + +extern nsIRDFCursor* gEmptyCursor; + +static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID); +static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID); +static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID); +static NS_DEFINE_IID(kIRDFRegistryIID, NS_IRDFREGISTRY_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static NS_DEFINE_CID(kRDFRegistryCID, NS_RDFREGISTRY_CID); + +//////////////////////////////////////////////////////////////////////// +// PropertyListElement + +class PropertyListElement { +private: + nsIRDFNode* mValue; + PRBool mTruthValue; + PropertyListElement* mNext; + PropertyListElement* mPrev; + +public: + PropertyListElement(nsIRDFNode* value, PRBool truthValue) + : mValue(value), mTruthValue(truthValue) { + mNext = mPrev = this; + NS_IF_ADDREF(mValue); + } + + ~PropertyListElement(void) { + NS_IF_RELEASE(mValue); + } + + nsIRDFNode* GetValue(void) { + return mValue; + } + + PRBool GetTruthValue(void) { + return mTruthValue; + } + + PropertyListElement* GetNext(void) { + return mNext; + } + + PropertyListElement* GetPrev(void) { + return mPrev; + } + + void InsertAfter(PropertyListElement* e) { + e->mNext->mPrev = this; + this->mNext = e->mNext; + e->mNext = this; + this->mPrev = e; + } + + PRBool UnlinkAndTestIfEmpty(void) { + if (mPrev == mNext) + return PR_TRUE; + + mPrev->mNext = mNext; + mNext->mPrev = mPrev; + return PR_FALSE; + } +}; + +//////////////////////////////////////////////////////////////////////// +// NodeImpl + +class NodeHashKey; + +class NodeImpl { +protected: + nsIRDFNode* mNode; + nsHashtable mProperties; // maps an nsIRDFNode* property to a property list + + inline PropertyListElement* FindPropertyValue(NodeHashKey* key, nsIRDFNode* value, PRBool tv); + +public: + NodeImpl(nsIRDFNode* node) : mNode(node) { + NS_IF_ADDREF(mNode); + } + + virtual ~NodeImpl(void); + + nsIRDFNode* GetNode(void) { + return mNode; + } + + PRBool HasPropertyValue(nsIRDFNode* property, nsIRDFNode* value, PRBool tv); + void AddProperty(nsIRDFNode* property, nsIRDFNode* value, PRBool tv); + void RemoveProperty(nsIRDFNode* property, nsIRDFNode* value); + nsIRDFNode* GetProperty(nsIRDFNode* property, PRBool tv); + nsIRDFCursor* GetProperties(nsIRDFNode* property, PRBool tv); + nsIRDFCursor* GetArcLabelsOut(void); +}; + +//////////////////////////////////////////////////////////////////////// +// NodeHashKey + +class NodeHashKey : public nsHashKey +{ +private: + nsIRDFNode* mNode; + +public: + NodeHashKey(void) : mNode(NULL) { + } + + NodeHashKey(nsIRDFNode* aNode) : mNode(aNode) { + NS_IF_ADDREF(mNode); + } + + NodeHashKey(const NodeHashKey& key) : mNode(key.mNode) { + NS_IF_ADDREF(mNode); + } + + NodeHashKey& operator=(const NodeHashKey& key) { + NS_IF_RELEASE(mNode); + mNode = key.mNode; + NS_IF_ADDREF(mNode); + return *this; + } + + NodeHashKey& operator=(nsIRDFNode* aNode) { + NS_IF_RELEASE(mNode); + mNode = aNode; + NS_IF_ADDREF(mNode); + return *this; + } + + virtual ~NodeHashKey(void) { + NS_IF_RELEASE(mNode); + } + + nsIRDFNode* GetNode(void) { + return mNode; + } + + // nsHashKey pure virtual interface methods + virtual PRUint32 HashValue(void) const { + return (PRUint32) mNode; + } + + virtual PRBool Equals(const nsHashKey* aKey) const { + NodeHashKey* that; + + //if (! (that = dynamic_cast(aKey))) + if (! (that = (NodeHashKey*)(aKey))) + return PR_FALSE; + + return (that->mNode == this->mNode); + } + + virtual nsHashKey* Clone(void) const { + return new NodeHashKey(mNode); + } +}; + + +//////////////////////////////////////////////////////////////////////// +// PropertyCursorImpl + +class PropertyCursorImpl : public nsIRDFCursor { +private: + PropertyListElement* mFirst; + PropertyListElement* mNext; + PRBool mTruthValueToMatch; + +public: + PropertyCursorImpl(PropertyListElement* first, PRBool truthValue); + virtual ~PropertyCursorImpl(void); + + NS_DECL_ISUPPORTS + + NS_IMETHOD HasMoreElements(PRBool& result); + NS_IMETHOD GetNext(nsIRDFNode*& next, PRBool& tv); +}; + + +PropertyCursorImpl::PropertyCursorImpl(PropertyListElement* first, PRBool truthValueToMatch) + : mFirst(first), + mNext(first), + mTruthValueToMatch(truthValueToMatch) +{ + NS_INIT_REFCNT(); + while (1) { + if (mNext->GetTruthValue() == mTruthValueToMatch) + break; + + if (mNext == mFirst) { + mNext = NULL; // wrapped all the way back to the start + break; + } + + mNext = mNext->GetNext(); + } +} + + +PropertyCursorImpl::~PropertyCursorImpl(void) +{ +} + +NS_IMPL_ISUPPORTS(PropertyCursorImpl, kIRDFCursorIID); + +NS_IMETHODIMP +PropertyCursorImpl::HasMoreElements(PRBool& result) +{ + result = (mNext != NULL); + return NS_OK; +} + + +NS_IMETHODIMP +PropertyCursorImpl::GetNext(nsIRDFNode*& next, PRBool& tv) +{ + if (mNext == NULL) + return NS_ERROR_UNEXPECTED; + + next = mNext->GetValue(); + tv = mNext->GetTruthValue(); + + mNext = mNext->GetNext(); // advance past the current node + while (1) { + if (mNext == mFirst) { + mNext = NULL; // wrapped all the way back to the start + break; + } + + if (mNext->GetTruthValue() == mTruthValueToMatch) + break; + + mNext = mNext->GetNext(); + } + + return NS_OK; +} + + + +//////////////////////////////////////////////////////////////////////// +// ArcCursorImpl + +class ArcCursorImpl : public nsIRDFCursor { +private: + nsISupportsArray* mProperties; + static PRBool Enumerator(nsHashKey* key, void* value, void* closure); + +public: + ArcCursorImpl(nsHashtable& properties); + virtual ~ArcCursorImpl(void); + + NS_DECL_ISUPPORTS + + NS_IMETHOD HasMoreElements(PRBool& result); + NS_IMETHOD GetNext(nsIRDFNode*& next, PRBool& tv); +}; + + +ArcCursorImpl::ArcCursorImpl(nsHashtable& properties) +{ + NS_INIT_REFCNT(); + if (NS_SUCCEEDED(NS_NewISupportsArray(&mProperties))) + properties.Enumerate(Enumerator, mProperties); +} + +ArcCursorImpl::~ArcCursorImpl(void) +{ + NS_IF_RELEASE(mProperties); +} + +NS_IMPL_ISUPPORTS(ArcCursorImpl, kIRDFCursorIID); + +PRBool +ArcCursorImpl::Enumerator(nsHashKey* key, void* value, void* closure) +{ + nsISupportsArray* properties = static_cast(closure); + NodeHashKey* k = (NodeHashKey*) key; + properties->AppendElement(k->GetNode()); + return PR_TRUE; +} + +NS_IMETHODIMP +ArcCursorImpl::HasMoreElements(PRBool& result) +{ + result = (mProperties && mProperties->Count() > 0); + return NS_OK; +} + + +NS_IMETHODIMP +ArcCursorImpl::GetNext(nsIRDFNode*& next, PRBool& tv) +{ + if (! mProperties || ! mProperties->Count()) + return NS_ERROR_UNEXPECTED; + + PRInt32 index = mProperties->Count() - 1; + nsISupports* obj = mProperties->ElementAt(index); // this'll AddRef() + + PR_ASSERT(obj); + if (obj) { + obj->QueryInterface(kIRDFNodeIID, (void**) &next); + obj->Release(); + } + + mProperties->RemoveElementAt(index); + + tv = PR_TRUE; // not really applicable... + return NS_OK; +} + + +//////////////////////////////////////////////////////////////////////// +// NodeImpl implementation + +NodeImpl::~NodeImpl(void) +{ + NS_IF_RELEASE(mNode); + + // XXX LEAK! we need to make sure that the properties are + // released! +} + + +PropertyListElement* +NodeImpl::FindPropertyValue(NodeHashKey* key, nsIRDFNode* value, PRBool tv) +{ + PropertyListElement* head + = static_cast(mProperties.Get(key)); + + if (! head) + return NULL; + + PropertyListElement* e = head; + do { + if (e->GetValue() == value && e->GetTruthValue() == tv) + return e; + + e = e->GetNext(); + } while (e != head); + + return NULL; +} + + +PRBool +NodeImpl::HasPropertyValue(nsIRDFNode* property, nsIRDFNode* value, PRBool tv) +{ + NodeHashKey key(property); + return (FindPropertyValue(&key, value, tv) != NULL); +} + +nsIRDFNode* +NodeImpl::GetProperty(nsIRDFNode* property, PRBool tv) +{ + NodeHashKey key(property); + PropertyListElement* head + = static_cast(mProperties.Get(&key)); + + if (! head) + return NULL; + + PropertyListElement* e = head; + do { + if (e->GetTruthValue() == tv) + return e->GetValue(); + + e = e->GetNext(); + } while (e != head); + + return NULL; +} + +void +NodeImpl::AddProperty(nsIRDFNode* property, nsIRDFNode* value, PRBool tv) +{ + NodeHashKey key(property); + if (FindPropertyValue(&key, value, tv)) + return; + + // XXX so both positive and negative assertions can live in the + // graph together. This seems wrong... + + PropertyListElement* head + = static_cast(mProperties.Get(&key)); + + PropertyListElement* e + = new PropertyListElement(value, tv); + + if (head) { + e->InsertAfter(head); + } else { + mProperties.Put(&key, e); + } +} + + +void +NodeImpl::RemoveProperty(nsIRDFNode* property, nsIRDFNode* value) +{ + NodeHashKey key(property); + PropertyListElement* e; + + // this is really bizarre that two truth values can live in one + // data source. I'm suspicious that this isn't quite right... + + e = FindPropertyValue(&key, value, PR_TRUE); + if (e) { + if (e->UnlinkAndTestIfEmpty()) + mProperties.Remove(&key); + delete e; + } + + e = FindPropertyValue(&key, value, PR_FALSE); + if (e) { + if (e->UnlinkAndTestIfEmpty()) + mProperties.Remove(&key); + delete e; + } +} + + +nsIRDFCursor* +NodeImpl::GetProperties(nsIRDFNode* property, PRBool tv) +{ + NodeHashKey key(property); + PropertyListElement* head + = static_cast(mProperties.Get(&key)); + + return (head) ? (new PropertyCursorImpl(head, tv)) : gEmptyCursor; +} + + +nsIRDFCursor* +NodeImpl::GetArcLabelsOut(void) +{ + return new ArcCursorImpl(mProperties); +} + +//////////////////////////////////////////////////////////////////////// +// nsMemoryDataSource implementation + +nsMemoryDataSource::nsMemoryDataSource(void) + : mRegistry(NULL) +{ + NS_INIT_REFCNT(); +} + + + +nsMemoryDataSource::~nsMemoryDataSource(void) +{ + // XXX LEAK! make sure that you release the nodes + if (mRegistry) { + mRegistry->Unregister(this); + nsServiceManager::ReleaseService(kRDFRegistryCID, mRegistry); + mRegistry = NULL; + } +} + +NS_IMPL_ISUPPORTS(nsMemoryDataSource, kIRDFDataSourceIID); + + +NS_IMETHODIMP +nsMemoryDataSource::Initialize(const nsString& uri) +{ + nsresult rv; + + if (mRegistry) + return NS_ERROR_ALREADY_INITIALIZED; + + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFRegistryCID, + kIRDFRegistryIID, + (nsISupports**) &mRegistry))) + return rv; + + return mRegistry->Register(uri, this); +} + +NS_IMETHODIMP +nsMemoryDataSource::GetSource(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFNode*& source) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; // XXX +} + +NS_IMETHODIMP +nsMemoryDataSource::GetSources(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFCursor*& sources) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; // XXX +} + +NS_IMETHODIMP +nsMemoryDataSource::GetTarget(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFNode*& target) +{ + NS_PRECONDITION(source && property, "null ptr"); + if (!source || !property) + return NS_ERROR_NULL_POINTER; + + target = NULL; // reasonable default + + NodeHashKey key(source); + NodeImpl *u; + + if (! (u = static_cast(mNodes.Get(&key)))) + return NS_ERROR_FAILURE; + + target = u->GetProperty(property, tv); + if (! target) + return NS_ERROR_FAILURE; + + NS_ADDREF(target); // need to AddRef() + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::GetTargets(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFCursor*& targets) +{ + NS_PRECONDITION(source && property, "null ptr"); + if (!source || !property) + return NS_ERROR_NULL_POINTER; + + targets = gEmptyCursor; // reasonable default + + NodeHashKey key(source); + NodeImpl *u; + if (! (u = static_cast(mNodes.Get(&key)))) + return NS_OK; + + if (! (targets = u->GetProperties(property, tv))) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(targets); + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::Assert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv) +{ + NS_PRECONDITION(source && property && target, "null ptr"); + if (!source || !property || !target) + return NS_ERROR_NULL_POINTER; + + NodeImpl *u; + + if (! (u = Ensure(source))) + return NS_ERROR_OUT_OF_MEMORY; + + if (! Ensure(property)) + return NS_ERROR_OUT_OF_MEMORY; + + if (! Ensure(target)) + return NS_ERROR_OUT_OF_MEMORY; + + u->AddProperty(property, target, tv); + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::Unassert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target) +{ + NS_PRECONDITION(source && property && target, "null ptr"); + if (!source || !property || !target) + return NS_ERROR_NULL_POINTER; + + NodeHashKey key(source); + NodeImpl *u; + + if (! (u = static_cast(mNodes.Get(&key)))) + return NS_OK; + + u->RemoveProperty(property, target); + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::HasAssertion(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + PRBool& hasAssertion) +{ + NS_PRECONDITION(source && property && target, "null ptr"); + if (!source || !property || !target) + return NS_ERROR_NULL_POINTER; + + hasAssertion = PR_FALSE; // reasonable default + + NodeHashKey key(source); + NodeImpl *u; + + if (! (u = static_cast(mNodes.Get(&key)))) + return NS_OK; + + hasAssertion = (u->GetProperty(property, tv) != NULL); + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::AddObserver(nsIRDFObserver* n) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsMemoryDataSource::RemoveObserver(nsIRDFObserver* n) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsMemoryDataSource::ArcLabelsIn(nsIRDFNode* node, + nsIRDFCursor*& labels) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsMemoryDataSource::ArcLabelsOut(nsIRDFNode* source, + nsIRDFCursor*& labels) +{ + NS_PRECONDITION(source, "null ptr"); + if (! source) + return NS_ERROR_NULL_POINTER; + + labels = gEmptyCursor; // reasonable default + + NodeHashKey key(source); + NodeImpl *u; + if (! (u = static_cast(mNodes.Get(&key)))) + return NS_OK; + + if (! (labels = u->GetArcLabelsOut())) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(labels); + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryDataSource::Flush() +{ + return NS_OK; // nothing to flush! +} + + + +NodeImpl* +nsMemoryDataSource::Ensure(nsIRDFNode* node) +{ + // The NodeHashKey does an AddRef(), and is cloned for insertion + // into the nsHashTable. This makes resource management really + // easy, because when the nsHashtable is destroyed, all of the + // keys are automatically deleted, which in turn does an + // appropriate Release() on the nsIRDFNode. + + NodeHashKey key(node); + NodeImpl* result = static_cast(mNodes.Get(&key)); + if (! result) { + result = new NodeImpl(node); + if (result) + mNodes.Put(&key, result); + } + return result; +} + + + diff --git a/rdf/src/nsMemoryDataSource.h b/rdf/src/nsMemoryDataSource.h new file mode 100644 index 000000000000..84061a7b0956 --- /dev/null +++ b/rdf/src/nsMemoryDataSource.h @@ -0,0 +1,97 @@ +/* -*- 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. + */ + +#ifndef nsMemoryDataSource_h__ +#define nsMemoryDataSource_h__ + +#include "prtypes.h" +#include "nsIRDFDataSource.h" +#include "nsHashtable.h" + +class nsIRDFNode; +class nsIRDFCursor; +class nsIRDFRegistry; +class NodeImpl; + +class nsMemoryDataSource : public nsIRDFDataSource { +protected: + nsHashtable mNodes; + nsIRDFRegistry* mRegistry; + + NodeImpl* Ensure(nsIRDFNode* node); + +public: + nsMemoryDataSource(void); + virtual ~nsMemoryDataSource(void); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIRDFDataSource methods + NS_IMETHOD Initialize(const nsString& uri); + + NS_IMETHOD GetSource(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFNode*& source); + + NS_IMETHOD GetSources(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFCursor*& sources); + + NS_IMETHOD GetTarget(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFNode*& target); + + NS_IMETHOD GetTargets(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFCursor*& targets); + + NS_IMETHOD Assert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv = PR_TRUE); + + NS_IMETHOD Unassert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target); + + NS_IMETHOD HasAssertion(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + PRBool& hasAssertion); + + NS_IMETHOD AddObserver(nsIRDFObserver* n); + + NS_IMETHOD RemoveObserver(nsIRDFObserver* n); + + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, + nsIRDFCursor*& labels); + + NS_IMETHOD ArcLabelsOut(nsIRDFNode* source, + nsIRDFCursor*& labels); + + NS_IMETHOD Flush(); +}; + + +#endif // nsMemoryDataSource_h__ diff --git a/rdf/src/nsRDFContentSink.cpp b/rdf/src/nsRDFContentSink.cpp new file mode 100644 index 000000000000..62440e46d607 --- /dev/null +++ b/rdf/src/nsRDFContentSink.cpp @@ -0,0 +1,1615 @@ +/* -*- 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. + */ + +/* + + This is an NGLayout-style content sink that knows how to build an + RDF content model from XML-serialized RDF. + + For more information on RDF, see http://www.w3.org/TR/WDf-rdf-syntax. + + This code is based on the working draft "last call", which was + published on Oct 8, 1998. + + Open Issues ------------------ + + 1) factoring code with nsXMLContentSink - There's some amount of + common code between this and the HTML content sink. This will + increase as we support more and more HTML elements. How can code + from the code be factored? + + TO DO ------------------------ + + 1) Using the nsIRDFContent and nsIRDFContainerContent interfaces to + actually build the content model is a red herring. What I + *really* want to do is just build an RDF graph, then let the + presentation actually generate the "content model" on demand. + + 2) Handle resource references in properties + + 3) Make sure all shortcut syntax works right. + +*/ + +#include "nsCRT.h" +#include "nsHTMLEntities.h" // XXX for NS_EntityToUnicode() +#include "nsICSSParser.h" +#include "nsIContent.h" +#include "nsIDOMComment.h" +#include "nsIDocument.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIRDFContent.h" +#include "nsIRDFContent.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFDocument.h" +#include "nsIRDFNode.h" +#include "nsIRDFResourceManager.h" +#include "nsIScriptContext.h" +#include "nsIScriptContextOwner.h" +#include "nsIScriptObjectOwner.h" +#include "nsIServiceManager.h" +#include "nsICSSStyleSheet.h" +#include "nsITextContent.h" +#include "nsIURL.h" +#include "nsIUnicharInputStream.h" +#include "nsIViewManager.h" +#include "nsIWebShell.h" +#include "nsIXMLContent.h" +#include "nsIXMLDocument.h" +#include "nsLayoutCID.h" +#include "nsRDFCID.h" +#include "nsRDFContentSink.h" +#include "nsVoidArray.h" +#include "prlog.h" +#include "prmem.h" +#include "prtime.h" + +static const char kNameSpaceSeparator[] = ":"; +static const char kNameSpaceDef[] = "xmlns"; +static const char kStyleSheetPI[] = "= 0) { + aResult.Cut(pos, 1); + } + } else { + // Mismatched quotes - leave them in + } + } + + // Reduce any entities + // XXX Note: as coded today, this will only convert well formed + // entities. This may not be compatible enough. + // XXX there is a table in navigator that translates some numeric entities + // should we be doing that? If so then it needs to live in two places (bad) + // so we should add a translate numeric entity method from the parser... + char cbuf[100]; + PRInt32 index = 0; + while (index < aResult.Length()) { + // If we have the start of an entity (and it's not at the end of + // our string) then translate the entity into it's unicode value. + if ((aResult.CharAt(index++) == '&') && (index < aResult.Length())) { + PRInt32 start = index - 1; + PRUnichar e = aResult.CharAt(index); + if (e == '#') { + // Convert a numeric character reference + index++; + char* cp = cbuf; + char* limit = cp + sizeof(cbuf) - 1; + PRBool ok = PR_FALSE; + PRInt32 slen = aResult.Length(); + while ((index < slen) && (cp < limit)) { + PRUnichar e = aResult.CharAt(index); + if (e == ';') { + index++; + ok = PR_TRUE; + break; + } + if ((e >= '0') && (e <= '9')) { + *cp++ = char(e); + index++; + continue; + } + break; + } + if (!ok || (cp == cbuf)) { + continue; + } + *cp = '\0'; + if (cp - cbuf > 5) { + continue; + } + PRInt32 ch = PRInt32( ::atoi(cbuf) ); + if (ch > 65535) { + continue; + } + + // Remove entity from string and replace it with the integer + // value. + aResult.Cut(start, index - start); + aResult.Insert(PRUnichar(ch), start); + index = start + 1; + } + else if (((e >= 'A') && (e <= 'Z')) || + ((e >= 'a') && (e <= 'z'))) { + // Convert a named entity + index++; + char* cp = cbuf; + char* limit = cp + sizeof(cbuf) - 1; + *cp++ = char(e); + PRBool ok = PR_FALSE; + PRInt32 slen = aResult.Length(); + while ((index < slen) && (cp < limit)) { + PRUnichar e = aResult.CharAt(index); + if (e == ';') { + index++; + ok = PR_TRUE; + break; + } + if (((e >= '0') && (e <= '9')) || + ((e >= 'A') && (e <= 'Z')) || + ((e >= 'a') && (e <= 'z'))) { + *cp++ = char(e); + index++; + continue; + } + break; + } + if (!ok || (cp == cbuf)) { + continue; + } + *cp = '\0'; + PRInt32 ch = NS_EntityToUnicode(cbuf); + if (ch < 0) { + continue; + } + + // Remove entity from string and replace it with the integer + // value. + aResult.Cut(start, index - start); + aResult.Insert(PRUnichar(ch), start); + index = start + 1; + } + else if (e == '{') { + // Convert a script entity + // XXX write me! + } + } + } +} + + +static void +rdf_FullyQualifyURI(const nsIURL* base, nsString& spec) +{ + // This is a fairly heavy-handed way to do this, but...I don't + // like typing. + nsIURL* url; + if (NS_SUCCEEDED(NS_NewURL(&url, base, spec))) { + url->ToString(spec); + url->Release(); + } +} + +//////////////////////////////////////////////////////////////////////// +// Factory method + +nsresult +NS_NewRDFContentSink(nsIRDFContentSink** aResult, + nsIDocument* aDoc, + nsIURL* aURL, + nsIWebShell* aWebShell) +{ + NS_PRECONDITION(nsnull != aResult, "null ptr"); + if (nsnull == aResult) { + return NS_ERROR_NULL_POINTER; + } + nsRDFContentSink* it; + NS_NEWXPCOM(it, nsRDFContentSink); + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult rv = it->Init(aDoc, aURL, aWebShell); + if (NS_OK != rv) { + delete it; + return rv; + } + return it->QueryInterface(kIRDFContentSinkIID, (void **)aResult); +} + + +//////////////////////////////////////////////////////////////////////// + + +nsRDFContentSink::nsRDFContentSink() +{ + NS_INIT_REFCNT(); + mDocument = nsnull; + mDocumentURL = nsnull; + mWebShell = nsnull; + mRootElement = nsnull; + mRDFResourceManager = nsnull; + mDataSource = nsnull; + mGenSym = 0; + mNameSpaces = nsnull; + mNestLevel = 0; + mContextStack = nsnull; + mText = nsnull; + mTextLength = 0; + mTextSize = 0; + mConstrainSize = PR_TRUE; +} + +nsRDFContentSink::~nsRDFContentSink() +{ + NS_IF_RELEASE(mDocument); + NS_IF_RELEASE(mDocumentURL); + NS_IF_RELEASE(mWebShell); + NS_IF_RELEASE(mRootElement); + if (mRDFResourceManager) { + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mRDFResourceManager); + } + NS_IF_RELEASE(mDataSource); + if (mNameSpaces) { + // There shouldn't be any here except in an error condition + PRInt32 i, count = mNameSpaces->Count(); + + for (i=0; i < count; i++) { + NameSpaceStruct *ns = (NameSpaceStruct *)mNameSpaces->ElementAt(i); + + if (nsnull != ns) { + NS_IF_RELEASE(ns->mPrefix); + delete ns; + } + } + delete mNameSpaces; + } + if (mContextStack) { + NS_PRECONDITION(GetCurrentNestLevel() == 0, "content stack not empty"); + + // XXX we should never need to do this, but, we'll write the + // code all the same. If someone left the content stack dirty, + // pop all the elements off the stack and release them. + while (GetCurrentNestLevel() > 0) { + nsIRDFNode* resource; + RDFContentSinkState state; + PopContext(resource, state); + NS_IF_RELEASE(resource); + } + + delete mContextStack; + } + PR_FREEIF(mText); +} + +//////////////////////////////////////////////////////////////////////// + +nsresult +nsRDFContentSink::Init(nsIDocument* aDoc, + nsIURL* aURL, + nsIWebShell* aContainer) +{ + NS_PRECONDITION(nsnull != aDoc, "null ptr"); + NS_PRECONDITION(nsnull != aURL, "null ptr"); + NS_PRECONDITION(nsnull != aContainer, "null ptr"); + if ((nsnull == aDoc) || (nsnull == aURL) || (nsnull == aContainer)) { + return NS_ERROR_NULL_POINTER; + } + + mDocument = aDoc; + NS_ADDREF(aDoc); + + mDocumentURL = aURL; + NS_ADDREF(aURL); + mWebShell = aContainer; + NS_ADDREF(aContainer); + + nsresult rv; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mRDFResourceManager))) + return rv; + + if (NS_FAILED(rv = nsRepository::CreateInstance(kRDFMemoryDataSourceCID, + NULL, + kIRDFDataSourceIID, + (void**) &mDataSource))) + return rv; + + nsIRDFDocument* rdfDoc; + if (NS_FAILED(rv = mDocument->QueryInterface(kIRDFDocumentIID, (void**) &rdfDoc))) + return rv; + + rv = rdfDoc->SetDataSource(mDataSource); + NS_RELEASE(rdfDoc); + + mState = eRDFContentSinkState_InProlog; + return rv; +} + +//////////////////////////////////////////////////////////////////////// +// nsISupports interface + +NS_IMPL_ADDREF(nsRDFContentSink); +NS_IMPL_RELEASE(nsRDFContentSink); + +NS_IMETHODIMP +nsRDFContentSink::QueryInterface(REFNSIID iid, void** result) +{ + NS_PRECONDITION(result, "null ptr"); + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = NULL; + if (iid.Equals(kIRDFContentSinkIID) || + iid.Equals(kIXMLContentSinkIID) || + iid.Equals(kIContentSinkIID) || + iid.Equals(kISupportsIID)) { + *result = static_cast(this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + +//////////////////////////////////////////////////////////////////////// +// nsIContentSink interface + +NS_IMETHODIMP +nsRDFContentSink::WillBuildModel(void) +{ + // Notify document that the load is beginning + mDocument->BeginLoad(); + nsresult result = NS_OK; + + return result; +} + +NS_IMETHODIMP +nsRDFContentSink::DidBuildModel(PRInt32 aQualityLevel) +{ + // XXX this is silly; who cares? + PRInt32 i, ns = mDocument->GetNumberOfShells(); + for (i = 0; i < ns; i++) { + nsIPresShell* shell = mDocument->GetShellAt(i); + if (nsnull != shell) { + nsIViewManager* vm = shell->GetViewManager(); + if(vm) { + vm->SetQuality(nsContentQuality(aQualityLevel)); + } + NS_RELEASE(vm); + NS_RELEASE(shell); + } + } + + StartLayout(); + + // XXX Should scroll to ref when that makes sense + // ScrollToRef(); + + mDocument->EndLoad(); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::WillInterrupt(void) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::WillResume(void) +{ + return NS_OK; +} + + + +NS_IMETHODIMP +nsRDFContentSink::OpenContainer(const nsIParserNode& aNode) +{ + // XXX Hopefully the parser will flag this before we get here. If + // we're in the epilog, there should be no new elements + NS_PRECONDITION(mState != eRDFContentSinkState_InEpilog, "tag in RDF doc epilog"); + + FlushText(); + + // We must register namespace declarations found in the attribute + // list of an element before creating the element. This is because + // the namespace prefix for an element might be declared within + // the attribute list. + FindNameSpaceAttributes(aNode); + + nsIContent* content = NULL; + nsresult result; + + RDFContentSinkState lastState = mState; + switch (mState) { + case eRDFContentSinkState_InProlog: + result = OpenRDF(aNode); + break; + + case eRDFContentSinkState_InDocumentElement: + result = OpenObject(aNode); + break; + + case eRDFContentSinkState_InDescriptionElement: + result = OpenProperty(aNode); + break; + + case eRDFContentSinkState_InContainerElement: + result = OpenMember(aNode); + break; + + case eRDFContentSinkState_InPropertyElement: + result = OpenValue(aNode); + break; + + case eRDFContentSinkState_InMemberElement: + result = OpenValue(aNode); + break; + + case eRDFContentSinkState_InEpilog: + PR_ASSERT(0); + result = NS_ERROR_UNEXPECTED; // XXX + break; + } + + return result; +} + +NS_IMETHODIMP +nsRDFContentSink::CloseContainer(const nsIParserNode& aNode) +{ + FlushText(); + + nsIRDFNode* resource; + if (NS_FAILED(PopContext(resource, mState))) { + // XXX parser didn't catch unmatched tags? + PR_ASSERT(0); + return NS_ERROR_UNEXPECTED; // XXX + } + + PRInt32 nestLevel = GetCurrentNestLevel(); + if (nestLevel == 0) + mState = eRDFContentSinkState_InEpilog; + + CloseNameSpacesAtNestLevel(nestLevel); + + NS_IF_RELEASE(resource); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFContentSink::AddLeaf(const nsIParserNode& aNode) +{ + // XXX For now, all leaf content is character data + AddCharacterData(aNode); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::NotifyError(nsresult aErrorResult) +{ + printf("nsRDFContentSink::NotifyError\n"); + return NS_OK; +} + +// nsIXMLContentSink +NS_IMETHODIMP +nsRDFContentSink::AddXMLDecl(const nsIParserNode& aNode) +{ + // XXX We'll ignore it for now + printf("nsRDFContentSink::AddXMLDecl\n"); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFContentSink::AddComment(const nsIParserNode& aNode) +{ + FlushText(); + nsAutoString text; + //nsIDOMComment *domComment; + nsresult result = NS_OK; + + text = aNode.GetText(); + + // XXX add comment here... + + return result; +} + + +NS_IMETHODIMP +nsRDFContentSink::AddProcessingInstruction(const nsIParserNode& aNode) +{ + FlushText(); + + // XXX For now, we don't add the PI to the content model. + // We just check for a style sheet PI + nsAutoString text, type, href; + PRInt32 offset; + nsresult result = NS_OK; + + text = aNode.GetText(); + + offset = text.Find(kStyleSheetPI); + // If it's a stylesheet PI... + if (0 == offset) { + result = rdf_GetQuotedAttributeValue(text, "href", href); + // If there was an error or there's no href, we can't do + // anything with this PI + if ((NS_OK != result) || (0 == href.Length())) { + return result; + } + + result = rdf_GetQuotedAttributeValue(text, "type", type); + if (NS_OK != result) { + return result; + } + + if (type.Equals(kCSSType)) { + nsIURL* url = nsnull; + nsIUnicharInputStream* uin = nsnull; + nsAutoString absURL; + nsIURL* docURL = mDocument->GetDocumentURL(); + nsAutoString emptyURL; + emptyURL.Truncate(); + result = NS_MakeAbsoluteURL(docURL, emptyURL, href, absURL); + if (NS_OK != result) { + return result; + } + NS_RELEASE(docURL); + result = NS_NewURL(&url, nsnull, absURL); + if (NS_OK != result) { + return result; + } + PRInt32 ec; + nsIInputStream* iin = url->Open(&ec); + if (nsnull == iin) { + NS_RELEASE(url); + return (nsresult) ec;/* XXX fix url->Open */ + } + result = NS_NewConverterStream(&uin, nsnull, iin); + NS_RELEASE(iin); + if (NS_OK != result) { + NS_RELEASE(url); + return result; + } + + result = LoadStyleSheet(url, uin); + NS_RELEASE(uin); + NS_RELEASE(url); + } + } + + return result; +} + +NS_IMETHODIMP +nsRDFContentSink::AddDocTypeDecl(const nsIParserNode& aNode) +{ + printf("nsRDFContentSink::AddDocTypeDecl\n"); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFContentSink::AddCharacterData(const nsIParserNode& aNode) +{ + nsAutoString text = aNode.GetText(); + + PRInt32 addLen = text.Length(); + if (0 == addLen) { + return NS_OK; + } + + // Create buffer when we first need it + if (0 == mTextSize) { + mText = (PRUnichar *) PR_MALLOC(sizeof(PRUnichar) * 4096); + if (nsnull == mText) { + return NS_ERROR_OUT_OF_MEMORY; + } + mTextSize = 4096; + } + + // Copy data from string into our buffer; flush buffer when it fills up + PRInt32 offset = 0; + while (0 != addLen) { + PRInt32 amount = mTextSize - mTextLength; + if (amount > addLen) { + amount = addLen; + } + if (0 == amount) { + if (mConstrainSize) { + nsresult rv = FlushText(); + if (NS_OK != rv) { + return rv; + } + } + else { + mTextSize += addLen; + mText = (PRUnichar *) PR_REALLOC(mText, sizeof(PRUnichar) * mTextSize); + if (nsnull == mText) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + } + memcpy(&mText[mTextLength], text.GetUnicode() + offset, + sizeof(PRUnichar) * amount); + mTextLength += amount; + offset += amount; + addLen -= amount; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::AddUnparsedEntity(const nsIParserNode& aNode) +{ + printf("nsRDFContentSink::AddUnparsedEntity\n"); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::AddNotation(const nsIParserNode& aNode) +{ + printf("nsRDFContentSink::AddNotation\n"); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFContentSink::AddEntityReference(const nsIParserNode& aNode) +{ + printf("nsRDFContentSink::AddEntityReference\n"); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// Implementation methods + +void +nsRDFContentSink::StartLayout() +{ + PRInt32 i, ns = mDocument->GetNumberOfShells(); + for (i = 0; i < ns; i++) { + nsIPresShell* shell = mDocument->GetShellAt(i); + if (nsnull != shell) { + // Make shell an observer for next time + shell->BeginObservingDocument(); + + // Resize-reflow this time + nsIPresContext* cx = shell->GetPresContext(); + nsRect r; + cx->GetVisibleArea(r); + shell->InitialReflow(r.width, r.height); + NS_RELEASE(cx); + + // Now trigger a refresh + nsIViewManager* vm = shell->GetViewManager(); + if (nsnull != vm) { + vm->EnableRefresh(); + NS_RELEASE(vm); + } + + NS_RELEASE(shell); + } + } + + // If the document we are loading has a reference or it is a top level + // frameset document, disable the scroll bars on the views. + const char* ref = mDocumentURL->GetRef(); + PRBool topLevelFrameset = PR_FALSE; + if (mWebShell) { + nsIWebShell* rootWebShell; + mWebShell->GetRootWebShell(rootWebShell); + if (mWebShell == rootWebShell) { + topLevelFrameset = PR_TRUE; + } + NS_IF_RELEASE(rootWebShell); + } + + if ((nsnull != ref) || topLevelFrameset) { + // XXX support more than one presentation-shell here + + // Get initial scroll preference and save it away; disable the + // scroll bars. + PRInt32 i, ns = mDocument->GetNumberOfShells(); + for (i = 0; i < ns; i++) { + nsIPresShell* shell = mDocument->GetShellAt(i); + if (nsnull != shell) { + nsIViewManager* vm = shell->GetViewManager(); + if (nsnull != vm) { + nsIView* rootView = nsnull; + vm->GetRootView(rootView); + if (nsnull != rootView) { + nsIScrollableView* sview = nsnull; + rootView->QueryInterface(kIScrollableViewIID, (void**) &sview); + if (nsnull != sview) { + if (topLevelFrameset) + mOriginalScrollPreference = nsScrollPreference_kNeverScroll; + else + sview->GetScrollPreference(mOriginalScrollPreference); + sview->SetScrollPreference(nsScrollPreference_kNeverScroll); + } + } + NS_RELEASE(vm); + } + NS_RELEASE(shell); + } + } + } +} + + +// XXX Borrowed from HTMLContentSink. Should be shared. +nsresult +nsRDFContentSink::LoadStyleSheet(nsIURL* aURL, + nsIUnicharInputStream* aUIN) +{ + /* XXX use repository */ + nsresult rv; + nsICSSParser* parser; + rv = nsRepository::CreateInstance(kCSSParserCID, + NULL, + kICSSParserIID, + (void**) &parser); + + if (NS_SUCCEEDED(rv)) { + nsICSSStyleSheet* sheet = nsnull; + // XXX note: we are ignoring rv until the error code stuff in the + // input routines is converted to use nsresult's + parser->Parse(aUIN, aURL, sheet); + if (nsnull != sheet) { + mDocument->AddStyleSheet(sheet); + NS_RELEASE(sheet); + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY;/* XXX */ + } + NS_RELEASE(parser); + } + return rv; +} + +//////////////////////////////////////////////////////////////////////// +// Text buffering + +static PRBool +rdf_IsDataInBuffer(PRUnichar* buffer, PRInt32 length) +{ + for (PRInt32 i = 0; i < length; ++i) { + if (buffer[i] == ' ' || + buffer[i] == '\t' || + buffer[i] == '\n' || + buffer[i] == '\r') + continue; + + return PR_TRUE; + } + return PR_FALSE; +} + + +nsresult +nsRDFContentSink::FlushText(PRBool aCreateTextNode, PRBool* aDidFlush) +{ + nsresult rv = NS_OK; + PRBool didFlush = PR_FALSE; + if (0 != mTextLength) { + if (aCreateTextNode && rdf_IsDataInBuffer(mText, mTextLength)) { + // XXX if there's anything but whitespace, then we'll + // create a text node. + + switch (mState) { + case eRDFContentSinkState_InMemberElement: + case eRDFContentSinkState_InPropertyElement: { + nsAutoString value; + value.Append(mText, mTextLength); + + rv = Assert(GetContextElement(1), + GetContextElement(0), + value); + + } break; + + default: + // just ignore it + break; + } + } + mTextLength = 0; + didFlush = PR_TRUE; + } + if (nsnull != aDidFlush) { + *aDidFlush = didFlush; + } + return rv; +} + + + +//////////////////////////////////////////////////////////////////////// +// Qualified name resolution + +nsresult +nsRDFContentSink::SplitQualifiedName(const nsString& aQualifiedName, + nsString& rNameSpaceURI, + nsString& rProperty) +{ + rProperty = aQualifiedName; + + nsAutoString nameSpace; + PRInt32 nsoffset = rProperty.Find(kNameSpaceSeparator); + if (-1 != nsoffset) { + rProperty.Left(nameSpace, nsoffset); + rProperty.Cut(0, nsoffset+1); + } + else { + nameSpace.Truncate(); // XXX isn't it empty already? + } + + nsresult rv; + nsIXMLDocument* xmlDoc; + if (NS_FAILED(rv = mDocument->QueryInterface(kIXMLDocumentIID, (void**) &xmlDoc))) + return rv; + + PRInt32 nameSpaceId = GetNameSpaceId(nameSpace); + rv = xmlDoc->GetNameSpaceURI(nameSpaceId, rNameSpaceURI); + NS_RELEASE(xmlDoc); + + return rv; +} + + +nsresult +nsRDFContentSink::GetIdAboutAttribute(const nsIParserNode& aNode, + nsString& rResource) +{ + // This corresponds to the dirty work of production [6.5] + nsAutoString k; + nsAutoString ns, attr; + PRInt32 ac = aNode.GetAttributeCount(); + + for (PRInt32 i = 0; i < ac; i++) { + // Get upper-cased key + const nsString& key = aNode.GetKeyAt(i); + if (NS_FAILED(SplitQualifiedName(key, ns, attr))) + continue; + + if (! ns.Equals(kRDFNameSpaceURI)) + continue; + + // XXX you can't specify both, but we'll just pick up the + // first thing that was specified and ignore the other. + + if (attr.Equals(kTagRDF_about)) { + rResource = aNode.GetValueAt(i); + rdf_StripAndConvert(rResource); + + return NS_OK; + } + + if (attr.Equals(kTagRDF_ID)) { + mDocumentURL->ToString(rResource); + nsAutoString tag = aNode.GetValueAt(i); + rdf_StripAndConvert(tag); + + if (rResource.Last() != '#' && tag.First() != '#') + rResource.Append('#'); + + rResource.Append(tag); + return NS_OK; + } + + // XXX we don't deal with aboutEach... + } + + // Otherwise, we couldn't find anything, so just gensym one... + mDocumentURL->ToString(rResource); + rResource.Append("#anonymous$"); + rResource.Append(mGenSym++, 10); + return NS_OK; +} + + +nsresult +nsRDFContentSink::GetResourceAttribute(const nsIParserNode& aNode, + nsString& rResource) +{ + nsAutoString k; + nsAutoString ns, attr; + PRInt32 ac = aNode.GetAttributeCount(); + + for (PRInt32 i = 0; i < ac; i++) { + // Get upper-cased key + const nsString& key = aNode.GetKeyAt(i); + if (NS_FAILED(SplitQualifiedName(key, ns, attr))) + continue; + + if (! ns.Equals(kRDFNameSpaceURI)) + continue; + + // XXX you can't specify both, but we'll just pick up the + // first thing that was specified and ignore the other. + + if (attr.Equals(kTagRDF_resource)) { + rResource = aNode.GetValueAt(i); + rdf_StripAndConvert(rResource); + rdf_FullyQualifyURI(mDocumentURL, rResource); + return NS_OK; + } + } + return NS_ERROR_FAILURE; +} + +nsresult +nsRDFContentSink::AddProperties(const nsIParserNode& aNode, + nsIRDFNode* aSubject) +{ + // Add tag attributes to the content attributes + nsAutoString k, v; + nsAutoString ns, attr; + PRInt32 ac = aNode.GetAttributeCount(); + + for (PRInt32 i = 0; i < ac; i++) { + // Get upper-cased key + const nsString& key = aNode.GetKeyAt(i); + if (NS_FAILED(SplitQualifiedName(key, ns, attr))) + continue; + + // skip rdf:about, rdf:ID, and rdf:resource attributes; these + // are all "special" and should've been dealt with by the + // caller. + if (ns.Equals(kRDFNameSpaceURI) && + (attr.Equals(kTagRDF_about) || + attr.Equals(kTagRDF_ID) || + attr.Equals(kTagRDF_resource))) + continue; + + v = aNode.GetValueAt(i); + rdf_StripAndConvert(v); + + k.Truncate(); + k.Append(ns); + k.Append(attr); + + // Add the attribute to RDF + Assert(aSubject, k, v); + } + return NS_OK; +} + + +//////////////////////////////////////////////////////////////////////// +// RDF-specific routines used to build the model + +nsresult +nsRDFContentSink::OpenRDF(const nsIParserNode& aNode) +{ + // ensure that we're actually reading RDF by making sure that the + // opening tag is , where "rdf:" corresponds to whatever + // they've declared the standard RDF namespace to be. + nsAutoString ns, tag; + + if (NS_FAILED(SplitQualifiedName(aNode.GetText(), ns, tag))) + return NS_ERROR_UNEXPECTED; + + if (! ns.Equals(kRDFNameSpaceURI)) + return NS_ERROR_UNEXPECTED; + + if (! tag.Equals(kTagRDF_RDF)) + return NS_ERROR_UNEXPECTED; + + PushContext(NULL, mState); + mState = eRDFContentSinkState_InDocumentElement; + return NS_OK; +} + + +nsresult +nsRDFContentSink::OpenObject(const nsIParserNode& aNode) +{ + // an "object" non-terminal is either a "description", a "typed + // node", or a "container", so this change the content sink's + // state appropriately. + + if (! mRDFResourceManager) + return NS_ERROR_NOT_INITIALIZED; + + nsAutoString ns, tag; + nsresult rv; + if (NS_FAILED(rv = SplitQualifiedName(aNode.GetText(), ns, tag))) + return rv; + + // Figure out the URI of this object, and create an RDF node for it. + nsAutoString uri; + if (NS_FAILED(rv = GetIdAboutAttribute(aNode, uri))) + return rv; + + nsIRDFNode* rdfResource; + if (NS_FAILED(rv = mRDFResourceManager->GetNode(uri, rdfResource))) + return rv; + + // Arbitrarily make the document root be the first container + // element in the RDF. + if (! mRootElement) { + nsIRDFContent* rdfElement; + if (NS_FAILED(rv = NS_NewRDFElement(&rdfElement))) + return rv; + + if (NS_FAILED(rv = rdfElement->SetDocument(mDocument, PR_FALSE))) { + NS_RELEASE(rdfElement); + return rv; + } + + if (NS_FAILED(rv = rdfElement->SetResource(uri))) { + NS_RELEASE(rdfElement); + return rv; + } + + mRootElement = static_cast(rdfElement); + mDocument->SetRootContent(mRootElement); + + // don't release the rdfElement since we're keeping + // a reference to it in mRootElement + } + + // If we're in a member or property element, then this is the cue + // that we need to hook the object up into the graph via the + // member/property. + switch (mState) { + case eRDFContentSinkState_InMemberElement: + case eRDFContentSinkState_InPropertyElement: { + Assert(GetContextElement(1), + GetContextElement(0), + rdfResource); + } break; + + default: + break; + } + + // Push the element onto the context stack + PushContext(rdfResource, mState); + + // Now figure out what kind of state transition we need to + // make. We'll either be going into a mode where we parse a + // description or a container. + PRBool isaTypedNode = PR_TRUE; + + if (ns.Equals(kRDFNameSpaceURI)) { + isaTypedNode = PR_FALSE; + + if (tag.Equals(kTagRDF_Description)) { + // it's a description + mState = eRDFContentSinkState_InDescriptionElement; + } + else if (tag.Equals(kTagRDF_Bag)) { + // it's a bag container + Assert(rdfResource, kURIRDF_instanceOf, kURIRDF_Bag); + mState = eRDFContentSinkState_InContainerElement; + } + else if (tag.Equals(kTagRDF_Seq)) { + // it's a seq container + Assert(rdfResource, kURIRDF_instanceOf, kURIRDF_Seq); + mState = eRDFContentSinkState_InContainerElement; + } + else if (tag.Equals(kTagRDF_Alt)) { + // it's an alt container + Assert(rdfResource, kURIRDF_instanceOf, kURIRDF_Alt); + mState = eRDFContentSinkState_InContainerElement; + } + else { + // heh, that's not *in* the RDF namespace: just treat it + // like a typed node + isaTypedNode = PR_TRUE; + } + } + if (isaTypedNode) { + // XXX destructively alter "ns" to contain the fully qualified + // tag name. We can do this 'cause we don't need it anymore... + ns.Append(tag); + Assert(rdfResource, kURIRDF_instanceOf, ns); + + mState = eRDFContentSinkState_InDescriptionElement; + } + + AddProperties(aNode, rdfResource); + NS_RELEASE(rdfResource); + + return NS_OK; +} + + +nsresult +nsRDFContentSink::OpenProperty(const nsIParserNode& aNode) +{ + if (! mRDFResourceManager) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv; + + // an "object" non-terminal is either a "description", a "typed + // node", or a "container", so this change the content sink's + // state appropriately. + nsAutoString ns, tag; + + if (NS_FAILED(rv = SplitQualifiedName(aNode.GetText(), ns, tag))) + return rv; + + // destructively alter "ns" to contain the fully qualified tag + // name. We can do this 'cause we don't need it anymore... + ns.Append(tag); + nsIRDFNode* rdfProperty; + if (NS_FAILED(rv = mRDFResourceManager->GetNode(ns, rdfProperty))) + return rv; + + nsAutoString resourceURI; + if (NS_SUCCEEDED(GetResourceAttribute(aNode, resourceURI))) { + // They specified an inline resource for the value of this + // property. Create an RDF resource for the inline resource + // URI, add the properties to it, and attach the inline + // resource to its parent. + nsIRDFNode* rdfResource; + if (NS_SUCCEEDED(rv = mRDFResourceManager->GetNode(resourceURI, rdfResource))) { + if (NS_SUCCEEDED(rv = AddProperties(aNode, rdfResource))) { + rv = Assert(GetContextElement(0), rdfProperty, rdfResource); + } + } + + // XXX ignore any failure from above... + PR_ASSERT(rv == NS_OK); + + // XXX Technically, we should _not_ fall through here and push + // the element onto the stack: this is supposed to be a closed + // node. But right now I'm lazy and the code will just Do The + // Right Thing so long as the RDF is well-formed. + } + + // Push the element onto the context stack and change state. + PushContext(rdfProperty, mState); + mState = eRDFContentSinkState_InPropertyElement; + + rdfProperty->Release(); + return NS_OK; +} + + +nsresult +nsRDFContentSink::OpenMember(const nsIParserNode& aNode) +{ + // ensure that we're actually reading a member element by making + // sure that the opening tag is , where "rdf:" corresponds + // to whatever they've declared the standard RDF namespace to be. + nsAutoString ns, tag; + + if (NS_FAILED(SplitQualifiedName(aNode.GetText(), ns, tag))) + return NS_ERROR_UNEXPECTED; + + if (! ns.Equals(kRDFNameSpaceURI)) + return NS_ERROR_UNEXPECTED; + + if (! tag.Equals(kTagRDF_li)) + return NS_ERROR_UNEXPECTED; + + // The parent element is the container. + nsIRDFNode* contextResource = GetContextElement(0); + if (! contextResource) + return NS_ERROR_NULL_POINTER; + + // XXX err...figure out where we're at + PRUint32 count = 1; + + nsAutoString ordinalURI(kRDFNameSpaceURI); + ordinalURI.Append('_'); + ordinalURI.Append(count + 1, 10); + + nsresult rv; + nsIRDFNode* ordinalResource; + if (NS_FAILED(rv = mRDFResourceManager->GetNode(ordinalURI, ordinalResource))) + return rv; + + nsAutoString resourceURI; + if (NS_SUCCEEDED(GetResourceAttribute(aNode, resourceURI))) { + // Okay, this node has an RDF:resource="..." attribute. That + // means that it's a "referenced item," as covered in [6.29]. + rv = Assert(contextResource, ordinalResource, resourceURI); + + // XXX Technically, we should _not_ fall through here and push + // the element onto the stack: this is supposed to be a closed + // node. But right now I'm lazy and the code will just Do The + // Right Thing so long as the RDF is well-formed. + } + + // Push it on to the content stack and change state. + PushContext(ordinalResource, mState); + mState = eRDFContentSinkState_InMemberElement; + + ordinalResource->Release(); + return rv; +} + + +nsresult +nsRDFContentSink::OpenValue(const nsIParserNode& aNode) +{ + // a "value" can either be an object or a string: we'll only get + // *here* if it's an object, as raw text is added as a leaf. + return OpenObject(aNode); +} + +//////////////////////////////////////////////////////////////////////// +// RDF Helper Methods + +nsresult +nsRDFContentSink::Assert(nsIRDFNode* subject, nsIRDFNode* predicate, nsIRDFNode* object) +{ + if (!mDataSource) + return NS_ERROR_NOT_INITIALIZED; + +#ifdef DEBUG_waterson + char buf[256]; + nsAutoString s; + + printf("assert [\n"); + + subject->GetStringValue(s); + printf(" %s\n", s.ToCString(buf, sizeof(buf))); + + predicate->GetStringValue(s); + printf(" %s\n", s.ToCString(buf, sizeof(buf))); + + object->GetStringValue(s); + printf(" %s\n", s.ToCString(buf, sizeof(buf))); + + printf("]\n"); +#endif + + return mDataSource->Assert(subject, predicate, object); +} + + +nsresult +nsRDFContentSink::Assert(nsIRDFNode* subject, nsIRDFNode* predicate, const nsString& objectLiteral) +{ + if (!mRDFResourceManager) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv; + nsIRDFNode* object; + if (NS_FAILED(rv = mRDFResourceManager->GetNode(objectLiteral, object))) + return rv; + + rv = Assert(subject, predicate, object); + NS_RELEASE(object); + + return rv; +} + +nsresult +nsRDFContentSink::Assert(nsIRDFNode* subject, const nsString& predicateURI, const nsString& objectLiteral) +{ + if (!mRDFResourceManager) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv; + nsIRDFNode* predicate; + if (NS_FAILED(rv = mRDFResourceManager->GetNode(predicateURI, predicate))) + return rv; + + rv = Assert(subject, predicate, objectLiteral); + NS_RELEASE(predicate); + + return rv; +} + + +//////////////////////////////////////////////////////////////////////// +// Content stack management + +struct RDFContextStackElement { + nsIRDFNode* mResource; + RDFContentSinkState mState; +}; + +nsIRDFNode* +nsRDFContentSink::GetContextElement(PRInt32 ancestor /* = 0 */) +{ + if ((nsnull == mContextStack) || + (ancestor >= mNestLevel)) { + return nsnull; + } + + RDFContextStackElement* e = + static_cast(mContextStack->ElementAt(mNestLevel-ancestor-1)); + + return e->mResource; +} + +PRInt32 +nsRDFContentSink::PushContext(nsIRDFNode *aResource, RDFContentSinkState aState) +{ + if (! mContextStack) { + mContextStack = new nsVoidArray(); + if (! mContextStack) + return 0; + } + + RDFContextStackElement* e = new RDFContextStackElement; + if (! e) + return mNestLevel; + + NS_IF_ADDREF(aResource); + e->mResource = aResource; + e->mState = aState; + + mContextStack->AppendElement(static_cast(e)); + return ++mNestLevel; +} + +nsresult +nsRDFContentSink::PopContext(nsIRDFNode*& rResource, RDFContentSinkState& rState) +{ + RDFContextStackElement* e; + if ((nsnull == mContextStack) || + (0 == mNestLevel)) { + return NS_ERROR_NULL_POINTER; + } + + --mNestLevel; + e = static_cast(mContextStack->ElementAt(mNestLevel)); + mContextStack->RemoveElementAt(mNestLevel); + + // don't bother Release()-ing: call it our implicit AddRef(). + rResource = e->mResource; + rState = e->mState; + + delete e; + return NS_OK; +} + +PRInt32 +nsRDFContentSink::GetCurrentNestLevel() +{ + return mNestLevel; +} + + +//////////////////////////////////////////////////////////////////////// +// Namespace management + +void +nsRDFContentSink::FindNameSpaceAttributes(const nsIParserNode& aNode) +{ + nsAutoString k, uri, prefix; + PRInt32 ac = aNode.GetAttributeCount(); + PRInt32 offset; + nsresult result = NS_OK; + + for (PRInt32 i = 0; i < ac; i++) { + const nsString& key = aNode.GetKeyAt(i); + k.Truncate(); + k.Append(key); + // Look for "xmlns" at the start of the attribute name + offset = k.Find(kNameSpaceDef); + if (0 == offset) { + prefix.Truncate(); + + PRUnichar next = k.CharAt(sizeof(kNameSpaceDef)-1); + // If the next character is a :, there is a namespace prefix + if (':' == next) { + k.Right(prefix, k.Length()-sizeof(kNameSpaceDef)); + } + + // Get the attribute value (the URI for the namespace) + uri = aNode.GetValueAt(i); + rdf_StripAndConvert(uri); + + // Open a local namespace + OpenNameSpace(prefix, uri); + } + } +} + +PRInt32 +nsRDFContentSink::OpenNameSpace(const nsString& aPrefix, const nsString& aURI) +{ + nsIAtom *nameSpaceAtom = nsnull; + PRInt32 id = gNameSpaceId_Unknown; + + nsIXMLDocument *xmlDoc; + nsresult result = mDocument->QueryInterface(kIXMLDocumentIID, + (void **)&xmlDoc); + if (NS_OK != result) + return id; + + if (0 < aPrefix.Length()) + nameSpaceAtom = NS_NewAtom(aPrefix); + + result = xmlDoc->RegisterNameSpace(nameSpaceAtom, aURI, id); + if (NS_OK == result) { + NameSpaceStruct *ns; + + ns = new NameSpaceStruct; + if (nsnull != ns) { + ns->mPrefix = nameSpaceAtom; + NS_IF_ADDREF(nameSpaceAtom); + ns->mId = id; + ns->mNestLevel = GetCurrentNestLevel(); + + if (nsnull == mNameSpaces) + mNameSpaces = new nsVoidArray(); + + // XXX Should check for duplication + mNameSpaces->AppendElement((void *)ns); + } + } + + NS_IF_RELEASE(nameSpaceAtom); + NS_RELEASE(xmlDoc); + + return id; +} + +PRInt32 +nsRDFContentSink::GetNameSpaceId(const nsString& aPrefix) +{ + nsIAtom *nameSpaceAtom = nsnull; + PRInt32 id = gNameSpaceId_Unknown; + PRInt32 i, count; + + if (nsnull == mNameSpaces) + return id; + + if (0 < aPrefix.Length()) + nameSpaceAtom = NS_NewAtom(aPrefix); + + count = mNameSpaces->Count(); + for (i = 0; i < count; i++) { + NameSpaceStruct *ns = (NameSpaceStruct *)mNameSpaces->ElementAt(i); + + if ((nsnull != ns) && (ns->mPrefix == nameSpaceAtom)) { + id = ns->mId; + break; + } + } + + NS_IF_RELEASE(nameSpaceAtom); + return id; +} + +void +nsRDFContentSink::CloseNameSpacesAtNestLevel(PRInt32 mNestLevel) +{ + PRInt32 nestLevel = GetCurrentNestLevel(); + + if (nsnull == mNameSpaces) { + return; + } + + PRInt32 i, count; + count = mNameSpaces->Count(); + // Go backwards so that we can delete as we go along + for (i = count; i >= 0; i--) { + NameSpaceStruct *ns = (NameSpaceStruct *)mNameSpaces->ElementAt(i); + + if ((nsnull != ns) && (ns->mNestLevel == nestLevel)) { + NS_IF_RELEASE(ns->mPrefix); + mNameSpaces->RemoveElementAt(i); + delete ns; + } + } +} diff --git a/rdf/src/nsRDFContentSink.h b/rdf/src/nsRDFContentSink.h new file mode 100644 index 000000000000..b815e15d4da1 --- /dev/null +++ b/rdf/src/nsRDFContentSink.h @@ -0,0 +1,153 @@ +/* -*- 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. + */ + +#ifndef nsRDFContentSink_h__ +#define nsRDFContentSink_h__ + +#include "nsIRDFContentSink.h" +#include "nsIViewManager.h" +#include "nsIScrollableView.h" + +class nsIDocument; +class nsIScriptObjectOwner; +class nsIURL; +class nsIWebShell; +class nsIContent; +class nsVoidArray; +class nsIRDFDocument; +class nsIRDFContent; +class nsIRDFNode; +class nsIRDFResourceManager; +class nsIUnicharInputStream; +class nsIStyleSheet; + +typedef enum { + eRDFContentSinkState_InProlog, + eRDFContentSinkState_InDocumentElement, + eRDFContentSinkState_InDescriptionElement, + eRDFContentSinkState_InContainerElement, + eRDFContentSinkState_InPropertyElement, + eRDFContentSinkState_InMemberElement, + eRDFContentSinkState_InEpilog +} RDFContentSinkState; + + +class nsRDFContentSink : public nsIRDFContentSink { +public: + nsRDFContentSink(); + ~nsRDFContentSink(); + + nsresult Init(nsIDocument* aDoc, + nsIURL* aURL, + nsIWebShell* aContainer); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIContentSink + NS_IMETHOD WillBuildModel(void); + NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel); + NS_IMETHOD WillInterrupt(void); + NS_IMETHOD WillResume(void); + NS_IMETHOD OpenContainer(const nsIParserNode& aNode); + NS_IMETHOD CloseContainer(const nsIParserNode& aNode); + NS_IMETHOD AddLeaf(const nsIParserNode& aNode); + NS_IMETHOD AddComment(const nsIParserNode& aNode); + NS_IMETHOD AddProcessingInstruction(const nsIParserNode& aNode); + NS_IMETHOD NotifyError(nsresult aErrorResult); + + // nsIXMLContentSink + NS_IMETHOD AddXMLDecl(const nsIParserNode& aNode); + NS_IMETHOD AddDocTypeDecl(const nsIParserNode& aNode); + NS_IMETHOD AddCharacterData(const nsIParserNode& aNode); + NS_IMETHOD AddUnparsedEntity(const nsIParserNode& aNode); + NS_IMETHOD AddNotation(const nsIParserNode& aNode); + NS_IMETHOD AddEntityReference(const nsIParserNode& aNode); + +protected: + void StartLayout(); + + nsresult LoadStyleSheet(nsIURL* aURL, + nsIUnicharInputStream* aUIN); + nsresult FlushText(PRBool aCreateTextNode=PR_TRUE, + PRBool* aDidFlush=nsnull); + + void FindNameSpaceAttributes(const nsIParserNode& aNode); + + // namespace management + PRInt32 OpenNameSpace(const nsString& aPrefix, const nsString& aURI); + PRInt32 GetNameSpaceId(const nsString& aPrefix); + void CloseNameSpacesAtNestLevel(PRInt32 mNestLevel); + + nsresult SplitQualifiedName(const nsString& aQualifiedName, + nsString& rNameSpaceURI, + nsString& rPropertyURI); + + // RDF-specific parsing + nsresult GetIdAboutAttribute(const nsIParserNode& aNode, nsString& rResource); + nsresult GetResourceAttribute(const nsIParserNode& aNode, nsString& rResource); + nsresult AddProperties(const nsIParserNode& aNode, nsIRDFNode* aSubject); + + nsresult OpenRDF(const nsIParserNode& aNode); + nsresult OpenObject(const nsIParserNode& aNode); + nsresult OpenProperty(const nsIParserNode& aNode); + nsresult OpenMember(const nsIParserNode& aNode); + nsresult OpenValue(const nsIParserNode& aNode); + + // RDF helper routines + nsresult Assert(nsIRDFNode* subject, nsIRDFNode* predicate, nsIRDFNode* object); + nsresult Assert(nsIRDFNode* subject, nsIRDFNode* predicate, const nsString& objectLiteral); + nsresult Assert(nsIRDFNode* subject, const nsString& predicateURI, const nsString& objectLiteral); + + // content stack management + PRInt32 PushContext(nsIRDFNode *aContext, RDFContentSinkState aState); + nsresult PopContext(nsIRDFNode*& rContext, RDFContentSinkState& rState); + nsIRDFNode* GetContextElement(PRInt32 ancestor = 0); + PRInt32 GetCurrentNestLevel(); + + struct NameSpaceStruct { + nsIAtom* mPrefix; + PRInt32 mId; + PRInt32 mNestLevel; + }; + + nsIDocument* mDocument; + nsIURL* mDocumentURL; + nsIWebShell* mWebShell; + nsIContent* mRootElement; + PRUint32 mGenSym; // for generating anonymous resources + + nsIRDFResourceManager* mRDFResourceManager; + nsIRDFDataSource* mDataSource; // XXX should this really be a rdf *db* vs. a raw datasource? + RDFContentSinkState mState; + nsVoidArray* mNameSpaces; + + PRInt32 mNestLevel; + nsVoidArray* mContextStack; + + nsIStyleSheet* mStyleSheet; + nsScrollPreference mOriginalScrollPreference; + + PRUnichar* mText; + PRInt32 mTextLength; + PRInt32 mTextSize; + PRBool mConstrainSize; +}; + +#endif // nsRDFContentSink_h__ diff --git a/rdf/src/nsRDFDataModel.cpp b/rdf/src/nsRDFDataModel.cpp deleted file mode 100644 index e104b206dbe3..000000000000 --- a/rdf/src/nsRDFDataModel.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* -*- 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. - */ - -/* - - This is mostly a naive re-implementation of ht.c. There is currently - lots of stuff missing. For example, sorting, drag-and-drop support, - the "local HT database" (whatever that was for), fast access into - the tree for GetNthItem(). The list goes on and on, and I'm sure - that I don't know the half of it. - -*/ - -#include "nsIDMWidget.h" -#include "nsRDFDataModel.h" -#include "nsRDFDataModelItem.h" -#include "nsIRDFDataBase.h" -#include "nsString.h" -#include "plstr.h" -#include "prprf.h" -#include "rdf-int.h" - -static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); -static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); - - -//////////////////////////////////////////////////////////////////////// -// Utility functions - -static RDF -rdf_GetDefaultDB(void) -{ - // hackery that I don't understand from HTRDF_GetDB() - static const char* gNavCenterDataSources1[15] = { - "rdf:localStore", - "rdf:remoteStore", - "rdf:bookmarks", - "rdf:remoteStore", - "rdf:history", - /* "rdf:ldap", */ - "rdf:esftp", - /* "rdf:mail", */ -#ifdef XP_MAC - "rdf:appletalk", -#endif - "rdf:lfs", - "rdf:ht", - "rdf:columns", - "rdf:find", - NULL - }; - - return RDF_GetDB(gNavCenterDataSources1); -} - - - -//////////////////////////////////////////////////////////////////////// - -nsRDFDataModel::nsRDFDataModel(void) - : mDB(NULL), - mRoot(NULL), - mWidget(NULL), - mArcProperty(NULL) -{ - PR_ASSERT(gCoreVocab); - if (gCoreVocab) { - mArcProperty = gCoreVocab->RDF_parent; - mArcType = eRDFArcType_Inbound; - } - - NS_INIT_REFCNT(); -} - -nsRDFDataModel::~nsRDFDataModel(void) -{ - if (mRoot) - mRoot->Release(); - - if (mDB) - RDF_ReleaseDB(mDB); -} - -NS_IMPL_ADDREF(nsRDFDataModel); -NS_IMPL_RELEASE(nsRDFDataModel); - -NS_IMPL_QUERY_INTERFACE(nsRDFDataModel, kIDataModelIID); - -//////////////////////////////////////////////////////////////////////// -// nsIDataModel interface - -NS_IMETHODIMP -nsRDFDataModel::InitFromURL(const nsString& aUrl) -{ - // XXX A ghastly simplification of HT_PaneFromURL() - char* url = aUrl.ToNewCString(); - - const char* dbstr[2]; - dbstr[0] = getBaseURL(url); - dbstr[1] = NULL; - - mDB = RDF_GetDB(dbstr); - PL_strfree(const_cast(dbstr[0])); - - // XXX now we try to find the top-level resource in the - // database. PR_FALSE indicates that, if it ain't there, don't - // create it. - RDF_Resource r = RDF_GetResource(mDB, url, PR_FALSE); - delete url; - - PR_ASSERT(r); - if (! r) - return NS_ERROR_UNEXPECTED; - - nsRDFDataModelItem* item; - nsresult res = CreateItem(r, item); - if (NS_FAILED(res)) - return res; - - if (mRoot) - mRoot->Release(); - - mRoot = item; // n.b. implicit AddRef() in CreateItem() - mRoot->SetOpenState(PR_TRUE); - - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFDataModel::InitFromResource(nsIDMItem* pItem) -{ - nsIRDFResource* resource; - if (NS_FAILED(pItem->QueryInterface(kIRDFResourceIID, (void**) &resource))) - return NS_ERROR_INVALID_ARG; - - nsresult res = NS_OK; - - do { - RDF_Resource r; - - if (NS_FAILED(res = resource->GetResource(r))) - break; - - nsRDFDataModelItem* item; - if (NS_FAILED(res = CreateItem(r, item))) - break; - - if (mRoot) - mRoot->Release(); - - mRoot = item; // n.b. implicit AddRef() in CreateItem() - mRoot->SetOpenState(PR_TRUE); - - if (mDB) - RDF_ReleaseDB(mDB); - - mDB = rdf_GetDefaultDB(); - } while (0); - - resource->Release(); - return NS_ERROR_UNEXPECTED; -} - - -NS_IMETHODIMP -nsRDFDataModel::GetDMWidget(nsIDMWidget*& widget) const -{ - NS_IF_ADDREF(mWidget); - widget = mWidget; - return NS_OK; -} - -NS_IMETHODIMP -nsRDFDataModel::SetDMWidget(nsIDMWidget* widget) -{ - NS_IF_ADDREF(widget); - NS_IF_RELEASE(mWidget); - mWidget = widget; - return NS_OK; -} - -NS_IMETHODIMP -nsRDFDataModel::GetStringPropertyValue(nsString& value, const nsString& property) const -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - - -NS_IMETHODIMP -nsRDFDataModel::GetIntPropertyValue(PRInt32& value, const nsString& property) const -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -//////////////////////////////////////////////////////////////////////// -// Implementation methods - diff --git a/rdf/src/nsRDFDataModel.h b/rdf/src/nsRDFDataModel.h deleted file mode 100644 index 0499b5259cdd..000000000000 --- a/rdf/src/nsRDFDataModel.h +++ /dev/null @@ -1,99 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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. - */ - -#ifndef nsRDFDataModel_h__ -#define nsRDFDataModel_h__ - -#include "nsIDataModel.h" -#include "rdf.h" // XXX - -class nsString; -class nsRDFDataModelItem; - -enum nsRDFArcType { - eRDFArcType_Outbound, // follow outbound arcs (e.g., children-of) - eRDFArcType_Inbound // follow inbound arcs (e.g., parent-of) -}; - -//////////////////////////////////////////////////////////////////////// - -class nsRDFDataModel : public nsIDataModel { -private: - // XXX eventually, when we XPCOM the back-end - //nsIRDFDataBase& mDB; - - RDF mDB; - nsRDFDataModelItem* mRoot; - nsIDMWidget* mWidget; - - RDF_Resource mArcProperty; - nsRDFArcType mArcType; - -public: - nsRDFDataModel(void); - virtual ~nsRDFDataModel(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports - - NS_DECL_ISUPPORTS - - //////////////////////////////////////////////////////////////////////// - // nsIDataModel interface - - // Initializers - NS_IMETHOD InitFromURL(const nsString& url); - NS_IMETHOD InitFromResource(nsIDMItem* pResource); - - // Inspectors - NS_IMETHOD GetDMWidget(nsIDMWidget*& pWidget) const; - - // Setters - NS_IMETHOD SetDMWidget(nsIDMWidget* pWidget); - - // Methods to query the data model for property values for an entire widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& property) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& property) const; - - //////////////////////////////////////////////////////////////////////// - // Implementation methods - - RDF GetDB(void) const { - return mDB; - } - - nsRDFDataModelItem* GetRoot(void) const { - return mRoot; - } - - RDF_Resource GetArcProperty(void) const { - return mArcProperty; - } - - nsRDFArcType GetArcType(void) const { - return mArcType; - } - - // Internal accessor for the widget. Just wraps a member variable access. - nsIDMWidget* GetWidget() { return mWidget; } - - virtual NS_METHOD - CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) = 0; -}; - -#endif // nsRDFDataModel_h__ diff --git a/rdf/src/nsRDFDataModelItem.cpp b/rdf/src/nsRDFDataModelItem.cpp deleted file mode 100644 index 5c6fb52abbc8..000000000000 --- a/rdf/src/nsRDFDataModelItem.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -*- 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 "nsRDFDataModel.h" -#include "nsRDFDataModelItem.h" -#include "rdf-int.h" - -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDMItemIID, NS_IDMITEM_IID); -static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); - -//////////////////////////////////////////////////////////////////////// - -nsRDFDataModelItem::nsRDFDataModelItem(nsRDFDataModel& model, RDF_Resource resource) - : mDataModel(model), - mResource(resource), - mOpen(PR_FALSE), - mParent(NULL), - mCachedSubtreeSize(1) -{ - NS_INIT_REFCNT(); -} - - -nsRDFDataModelItem::~nsRDFDataModelItem(void) -{ - for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { - nsRDFDataModelItem* child = static_cast(mChildren[i]); - child->Release(); - } -} - -NS_IMPL_ADDREF(nsRDFDataModelItem); -NS_IMPL_RELEASE(nsRDFDataModelItem); - -NS_IMETHODIMP -nsRDFDataModelItem::QueryInterface(const nsIID& iid, void** result) -{ - if (! result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kIDMItemIID) || - iid.Equals(kISupportsIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - else if (iid.Equals(kIRDFResourceIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - return NS_ERROR_NO_INTERFACE; -} - - -//////////////////////////////////////////////////////////////////////// -// nsIDMItem interface - -NS_IMETHODIMP -nsRDFDataModelItem::GetIconImage(nsIImage*& image, nsIImageGroup* group) const -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - - - -NS_IMETHODIMP -nsRDFDataModelItem::GetOpenState(PRBool& result) const -{ - result = IsOpen(); - return NS_OK; -} - -// XXX I assume this is coming... -NS_IMETHODIMP -nsRDFDataModelItem::SetOpenState(PRBool open) -{ - if (open) - Open(); - else - Close(); - - return NS_OK; -} - -NS_IMETHODIMP -nsRDFDataModelItem::GetChildCount(PRUint32& count) const -{ - count = mChildren.GetSize(); - return NS_OK; -} - - - -NS_IMETHODIMP -nsRDFDataModelItem::GetNthChild(nsIDMItem*& pItem, PRUint32 n) const -{ - if (n < 0 || n > mChildren.GetUpperBound()) - return NS_ERROR_UNEXPECTED; // XXX - - pItem = static_cast(mChildren[n]); - pItem->AddRef(); - - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFDataModelItem::GetSubtreeSize(PRUint32& result) const -{ - if (! mCachedSubtreeSize) { - mCachedSubtreeSize = 1; // me - - for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { - nsRDFDataModelItem* child = - static_cast(mChildren[i]); - - PRUint32 childSubtreeSize; - child->GetSubtreeSize(childSubtreeSize); - mCachedSubtreeSize += childSubtreeSize; - } - } - result = mCachedSubtreeSize; - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFDataModelItem::GetParent(nsIDMItem*& pItem) const -{ - pItem = static_cast(mParent); - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFDataModelItem::GetStringPropertyValue(nsString& result, const nsString& property) const -{ - // 1. convert the property to a URI - // 2. ask the RDF database for the value of the property - return NS_ERROR_NOT_IMPLEMENTED; -} - - -NS_IMETHODIMP -nsRDFDataModelItem::GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - - -//////////////////////////////////////////////////////////////////////// -// nsIRDFResource interface - -NS_IMETHODIMP -nsRDFDataModelItem::GetResource(RDF_Resource& resource /* out */) const -{ - resource = mResource; - return NS_OK; -} - - -//////////////////////////////////////////////////////////////////////// -// Implementation methods - -void -nsRDFDataModelItem::InvalidateCachedSubtreeSize(void) -{ - if (mCachedSubtreeSize) { - mCachedSubtreeSize = 0; - if (mParent) - mParent->InvalidateCachedSubtreeSize(); - } -} - - - -void -nsRDFDataModelItem::AddChild(nsRDFDataModelItem* child) -{ - mChildren.Add(child); - nsRDFDataModelItem* item = this; - while (item) { - PRUint32 subtreeSize; - child->GetSubtreeSize(subtreeSize); - item->mCachedSubtreeSize += subtreeSize; - item = item->mParent; - } -} - - -void -nsRDFDataModelItem::Open(void) -{ - RDF_Cursor cursor; - if (mDataModel.GetArcType() == eRDFArcType_Outbound) { - // Arcs are outbound, that is, from a parent to it's - // child. Find all targets whose source is "me". - cursor = RDF_GetTargets(mDataModel.GetDB(), - mResource, - mDataModel.GetArcProperty(), - RDF_RESOURCE_TYPE, - PR_TRUE); - } - else { - // Arcs are inbound, that is, from a child to it's - // parent. Find all sources whose target is "me". - cursor = RDF_GetSources(mDataModel.GetDB(), - mResource, - mDataModel.GetArcProperty(), - RDF_RESOURCE_TYPE, - PR_TRUE); - } - - if (cursor) { - RDF_Resource r; - while ((r = static_cast(RDF_NextValue(cursor))) != NULL) { - nsRDFDataModelItem* child; - if (NS_FAILED(mDataModel.CreateItem(r, child))) - continue; - - // CreateItem() will have done an AddRef(), like a good - // COM citizen... - mChildren.Add(child); - child->mParent = this; - } - RDF_DisposeCursor(cursor); - } - - InvalidateCachedSubtreeSize(); - mOpen = PR_TRUE; -} - - -void -nsRDFDataModelItem::Close(void) -{ - for (PRUint32 i = 0; i < mChildren.GetSize(); ++i) { - nsRDFDataModelItem* child = static_cast(mChildren[i]); - child->Release(); - } - - InvalidateCachedSubtreeSize(); - mOpen = PR_FALSE; -} diff --git a/rdf/src/nsRDFDataModelItem.h b/rdf/src/nsRDFDataModelItem.h deleted file mode 100644 index e7a9dea93d66..000000000000 --- a/rdf/src/nsRDFDataModelItem.h +++ /dev/null @@ -1,118 +0,0 @@ -/* -*- 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. - */ - -#ifndef nsRDFDataModelItem_h__ -#define nsRDFDataModelItem_h__ - -#include "rdf.h" -#include "nsIDMItem.h" -#include "nsIRDFResource.h" -#include "nsVector.h" - -class nsRDFDataModel; - -//////////////////////////////////////////////////////////////////////// - -class nsRDFDataModelItem : public nsIDMItem, public nsIRDFResource { -private: - nsRDFDataModel& mDataModel; - RDF_Resource mResource; - PRBool mOpen; - nsVector mChildren; - nsRDFDataModelItem* mParent; - - /** - * A cached value for the size of this item's subtree. Zero means "invalid" - * or "unknown", and the next call to GetSubtreeSize() will force it to be - * recomputed. - */ - mutable PRUint32 mCachedSubtreeSize; - - void InvalidateCachedSubtreeSize(void); - -public: - nsRDFDataModelItem(nsRDFDataModel& model, RDF_Resource resource); - virtual ~nsRDFDataModelItem(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface - - NS_DECL_ISUPPORTS - - //////////////////////////////////////////////////////////////////////// - // nsIDMItem interface - - // Inspectors - NS_IMETHOD GetIconImage(nsIImage*& pImage, nsIImageGroup* pGroup) const; - NS_IMETHOD GetOpenState(PRBool& answer) const; - - // Methods for iterating over children. - NS_IMETHOD GetChildCount(PRUint32& count) const; - NS_IMETHOD GetNthChild(nsIDMItem*& pItem, PRUint32 item) const; - NS_IMETHOD GetSubtreeSize(PRUint32& result) const; - - // Parent access - NS_IMETHOD GetParent(nsIDMItem*& pItem) const; - - // Setters - NS_IMETHOD SetOpenState(PRBool state); // XXX not there yet... - - // Methods to query the data model for a specific item displayed within the widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& itemProperty) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const; - - //////////////////////////////////////////////////////////////////////// - // nsIRDFResource interface - - NS_IMETHOD GetResource(RDF_Resource& resource /* out */) const; - - //////////////////////////////////////////////////////////////////////// - // Implementation methods - - - nsRDFDataModel& GetDataModel(void) const { - return mDataModel; - } - - PRBool IsOpen(void) const { - return mOpen; - } - - void Open(void); - void Close(void); - - nsRDFDataModelItem* ChildAt(PRUint32 index) const { - return static_cast(mChildren[index]); - } - - void AddChild(nsRDFDataModelItem* child); - - PRUint32 GetChildCount(void) const { - return mChildren.GetSize(); - } - - nsRDFDataModelItem* GetParent(void) const { - return mParent; - } -}; - -//////////////////////////////////////////////////////////////////////// - - -#endif // nsRDFDataModelItem_h__ - diff --git a/rdf/src/nsRDFDocument.cpp b/rdf/src/nsRDFDocument.cpp new file mode 100644 index 000000000000..3afb8d111d19 --- /dev/null +++ b/rdf/src/nsRDFDocument.cpp @@ -0,0 +1,311 @@ +/* -*- 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. + */ + +#include "nsIDTD.h" +#include "nsIParser.h" +#include "nsIRDFContentSink.h" +#include "nsIStreamListener.h" +#include "nsIWebShell.h" +#include "nsIURL.h" +#include "nsParserCIID.h" +#include "nsRDFDocument.h" +#include "nsWellFormedDTD.h" + +#include "nsRDFCID.h" +#include "nsIRDFDataBase.h" +#include "nsIRDFDataSource.h" +#include "nsIRDFNode.h" + +#include "nsIHTMLStyleSheet.h" // for basic styles + +static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID); +static NS_DEFINE_IID(kIParserIID, NS_IPARSER_IID); +static NS_DEFINE_IID(kIRDFDocumentIID, NS_IRDFDOCUMENT_IID); +static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID); +static NS_DEFINE_IID(kIXMLDocumentIID, NS_IXMLDOCUMENT_IID); +static NS_DEFINE_IID(kIRDFDataBaseIID, NS_IRDFDATABASE_IID); + +static NS_DEFINE_CID(kRDFSimpleDataBaseCID, NS_RDFSIMPLEDATABASE_CID); + +struct NameSpaceStruct { + nsIAtom* mPrefix; + nsString mURI; +}; + +//////////////////////////////////////////////////////////////////////// + +nsRDFDocument::nsRDFDocument() + : mParser(NULL), + mNameSpaces(NULL), + mDB(NULL) +{ +} + +nsRDFDocument::~nsRDFDocument() +{ + NS_IF_RELEASE(mParser); + if (mNameSpaces) { + for (PRInt32 i = 0; i < mNameSpaces->Count(); ++i) { + NameSpaceStruct* ns = + static_cast(mNameSpaces->ElementAt(i)); + + if (! ns) + continue; + + NS_IF_RELEASE(ns->mPrefix); + delete ns; + } + delete mNameSpaces; + mNameSpaces = NULL; + } + NS_IF_RELEASE(mDB); +} + +NS_IMETHODIMP +nsRDFDocument::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = NULL; + if (iid.Equals(kIRDFDocumentIID) || + iid.Equals(kIXMLDocumentIID)) { + *result = static_cast(this); + AddRef(); + return NS_OK; + } + return nsMarkupDocument::QueryInterface(iid, result); +} + +nsrefcnt nsRDFDocument::AddRef() +{ + return nsDocument::AddRef(); +} + +nsrefcnt nsRDFDocument::Release() +{ + return nsDocument::Release(); +} + + +NS_IMETHODIMP +nsRDFDocument::StartDocumentLoad(nsIURL *aUrl, + nsIContentViewerContainer* aContainer, + nsIStreamListener **aDocListener, + const char* aCommand) +{ + nsresult rv = nsDocument::StartDocumentLoad(aUrl, aContainer, + aDocListener); + + if (NS_FAILED(rv)) { + return rv; + } + + nsIWebShell* webShell; + + static NS_DEFINE_IID(kCParserIID, NS_IPARSER_IID); + static NS_DEFINE_IID(kCParserCID, NS_PARSER_IID); + + rv = nsRepository::CreateInstance(kCParserCID, + nsnull, + kCParserIID, + (void **)&mParser); + if (NS_OK == rv) { + nsIRDFContentSink* sink; + + aContainer->QueryInterface(kIWebShellIID, (void**)&webShell); + rv = NS_NewRDFContentSink(&sink, this, aUrl, webShell); + NS_IF_RELEASE(webShell); + + if (NS_OK == rv) { + // For the HTML content within a document + nsIHTMLStyleSheet* mAttrStyleSheet; + if (NS_OK == NS_NewHTMLStyleSheet(&mAttrStyleSheet, aUrl, this)) { + AddStyleSheet(mAttrStyleSheet); // tell the world about our new style sheet + } + + // Set the parser as the stream listener for the document loader... + static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID); + rv = mParser->QueryInterface(kIStreamListenerIID, (void**)aDocListener); + + if (NS_OK == rv) { + + nsIDTD* theDTD=0; + // XXX For now, we'll use the "well formed" DTD + NS_NewWellFormed_DTD(&theDTD); + mParser->RegisterDTD(theDTD); + mParser->SetCommand(aCommand); + mParser->SetContentSink(sink); + mParser->Parse(aUrl); + } + NS_RELEASE(sink); + } + } + + return rv; +} + +NS_IMETHODIMP +nsRDFDocument::EndLoad() +{ + NS_IF_RELEASE(mParser); + return nsDocument::EndLoad(); +} + + +//////////////////////////////////////////////////////////////////////// +// nsIXMLDocument interface + +NS_IMETHODIMP +nsRDFDocument::RegisterNameSpace(nsIAtom* aPrefix, const nsString& aURI, + PRInt32& aNameSpaceId) +{ + if (! mNameSpaces) { + mNameSpaces = new nsVoidArray(); + if (! mNameSpaces) + return NS_ERROR_OUT_OF_MEMORY; + } + + NameSpaceStruct* ns = new NameSpaceStruct; + if (! ns) + return NS_ERROR_OUT_OF_MEMORY; + + NS_IF_ADDREF(aPrefix); + ns->mPrefix = aPrefix; + ns->mURI = aURI; + + aNameSpaceId = mNameSpaces->Count(); // just an index into the array + mNameSpaces->AppendElement(static_cast(ns)); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFDocument::GetNameSpaceURI(PRInt32 aNameSpaceId, nsString& aURI) +{ + if (! mNameSpaces) + return NS_ERROR_NULL_POINTER; + + if (aNameSpaceId < 0 || aNameSpaceId >= mNameSpaces->Count()) + return NS_ERROR_INVALID_ARG; + + NameSpaceStruct* ns = + static_cast(mNameSpaces->ElementAt(aNameSpaceId)); + + if (! ns) + return NS_ERROR_NULL_POINTER; + + aURI = ns->mURI; + return NS_OK; +} + +NS_IMETHODIMP +nsRDFDocument::GetNameSpacePrefix(PRInt32 aNameSpaceId, nsIAtom*& aPrefix) +{ + if (! mNameSpaces) + return NS_ERROR_NULL_POINTER; + + if (aNameSpaceId < 0 || aNameSpaceId >= mNameSpaces->Count()) + return NS_ERROR_INVALID_ARG; + + NameSpaceStruct* ns = + static_cast(mNameSpaces->ElementAt(aNameSpaceId)); + + if (! ns) + return NS_ERROR_NULL_POINTER; + + aPrefix = ns->mPrefix; + NS_IF_ADDREF(aPrefix); + + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFDocument::PrologElementAt(PRInt32 aOffset, nsIContent** aContent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFDocument::PrologCount(PRInt32* aCount) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFDocument::AppendToProlog(nsIContent* aContent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFDocument::EpilogElementAt(PRInt32 aOffset, nsIContent** aContent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFDocument::EpilogCount(PRInt32* aCount) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFDocument::AppendToEpilog(nsIContent* aContent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + + + +//////////////////////////////////////////////////////////////////////// +// nsIRDFDocument interface + +NS_IMETHODIMP +nsRDFDocument::GetDataBase(nsIRDFDataBase*& result) +{ + if (! mDB) + return NS_ERROR_NOT_INITIALIZED; + + result = mDB; + result->AddRef(); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFDocument::SetDataSource(nsIRDFDataSource* ds) +{ + NS_IF_RELEASE(mDB); + + nsresult rv; + rv = nsRepository::CreateInstance(kRDFSimpleDataBaseCID, + NULL, + kIRDFDataBaseIID, + (void**) &mDB); + + if (NS_FAILED(rv)) + return rv; + + rv = mDB->AddDataSource(ds); + return rv; +} diff --git a/rdf/src/nsRDFDocument.h b/rdf/src/nsRDFDocument.h new file mode 100644 index 000000000000..4c2e4b1f2fa7 --- /dev/null +++ b/rdf/src/nsRDFDocument.h @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef nsRDFDocument_h___ +#define nsRDFDocument_h___ + +#include "nsMarkupDocument.h" +#include "nsIRDFDocument.h" + +class nsIParser; + +class nsRDFDocument : public nsMarkupDocument, + public nsIRDFDocument +{ +public: + nsRDFDocument(); + virtual ~nsRDFDocument(); + + // nsISupports + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + // Override nsDocument's implementation + NS_IMETHOD StartDocumentLoad(nsIURL *aUrl, + nsIContentViewerContainer* aContainer, + nsIStreamListener **aDocListener, + const char* aCommand); + + NS_IMETHOD EndLoad(); + + + // nsIXMLDocument interface + NS_IMETHOD RegisterNameSpace(nsIAtom* aPrefix, const nsString& aURI, + PRInt32& aNameSpaceId); + + NS_IMETHOD GetNameSpaceURI(PRInt32 aNameSpaceId, nsString& aURI); + NS_IMETHOD GetNameSpacePrefix(PRInt32 aNameSpaceId, nsIAtom*& aPrefix); + + NS_IMETHOD PrologElementAt(PRInt32 aOffset, nsIContent** aContent); + NS_IMETHOD PrologCount(PRInt32* aCount); + NS_IMETHOD AppendToProlog(nsIContent* aContent); + + NS_IMETHOD EpilogElementAt(PRInt32 aOffset, nsIContent** aContent); + NS_IMETHOD EpilogCount(PRInt32* aCount); + NS_IMETHOD AppendToEpilog(nsIContent* aContent); + + // nsIRDFDocument interface + NS_IMETHOD GetDataBase(nsIRDFDataBase*& result); + NS_IMETHOD SetDataSource(nsIRDFDataSource* ds); + +protected: + nsVoidArray* mNameSpaces; + nsIParser* mParser; + nsIRDFDataBase* mDB; +}; + + +#endif // nsRDFDocument_h___ diff --git a/rdf/src/nsRDFElement.cpp b/rdf/src/nsRDFElement.cpp new file mode 100644 index 000000000000..a1a875e90d9c --- /dev/null +++ b/rdf/src/nsRDFElement.cpp @@ -0,0 +1,1472 @@ +/* -*- 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. + */ + +/* + + A "pseudo content element" that acts as a proxy to RDF. + + Unfortunately, there is no one right way to transform RDF into a + document model. Ideally, one would like to use something like XSL to + define how to do it in a declarative, user-definable way. But since + we don't have XSL yet, that's not an option. So here we have a + hard-coded implementation that does the job. + + TO DO + + 1) In the absence of XSL, at least factor out the strategy used to + build the content model so that multiple models can be build + (e.g., table-like HTML vs. XUI tree control, etc.) + + This involves both hacking the code that generates children for + presentation, and the code that manipulates children via the DOM, + which leads us to the next item... + + 2) Implement DOM interfaces. + + */ + +#include "nsRDFElement.h" +#include "nsHTMLParts.h" // XXX to create a text node +#include "nsIDocument.h" +#include "nsIDOMNodeList.h" +#include "nsIAtom.h" +#include "nsIEventListenerManager.h" +#include "nsIHTMLAttributes.h" +#include "nsIDOMScriptObjectFactory.h" +#include "nsIServiceManager.h" +#include "nsRDFCID.h" +#include "nsIRDFNode.h" +#include "nsIRDFResourceManager.h" +#include "nsIRDFDocument.h" +#include "nsIRDFDataBase.h" +#include "nsIRDFCursor.h" +#include "nsISupportsArray.h" +#include "nsITextContent.h" + +#include "nsIEventStateManager.h" +#include "nsDOMEvent.h" + +//////////////////////////////////////////////////////////////////////// +// RDF core vocabulary + +#include "rdf.h" +#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, Alt); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Bag); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Description); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, ID); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, RDF); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, Seq); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, about); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, aboutEach); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, bagID); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, instanceOf); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, li); +DEFINE_RDF_VOCAB(RDF_NAMESPACE_URI, RDF, resource); + +//////////////////////////////////////////////////////////////////////// + +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); +static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); +static NS_DEFINE_IID(kIJSScriptObjectIID, NS_IJSSCRIPTOBJECT_IID); +static NS_DEFINE_IID(kIDOMNodeListIID, NS_IDOMNODELIST_IID); +static NS_DEFINE_IID(kIDocumentIID, NS_IDOCUMENT_IID); +static NS_DEFINE_IID(kIRDFContentIID, NS_IRDFCONTENT_IID); +static NS_DEFINE_IID(kIRDFDataBaseIID, NS_IRDFDATABASE_IID); +static NS_DEFINE_IID(kIRDFDocumentIID, NS_IRDFDOCUMENT_IID); +static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID); +static NS_DEFINE_IID(kITextContentIID, NS_ITEXT_CONTENT_IID); // XXX grr... +static NS_DEFINE_IID(kIXMLContentIID, NS_IXMLCONTENT_IID); + +static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID); + +//////////////////////////////////////////////////////////////////////// +// Utility functions + +// XXX all of these should go to some generic RDF utility interface +// that lives in rdf.dll + +static PRBool +rdf_IsOrdinalProperty(const nsString& uri) +{ + if (uri.Find(kRDFNameSpaceURI) != 0) + return PR_FALSE; + + nsAutoString tag(uri); + tag.Cut(0, sizeof(kRDFNameSpaceURI) - 1); + + if (tag[0] != '_') + return PR_FALSE; + + for (PRInt32 i = tag.Length() - 1; i >= 1; --i) { + if (tag[i] < '0' || tag[i] > '9') + return PR_FALSE; + } + + return PR_TRUE; +} + + +static PRBool +rdf_IsContainer(nsIRDFResourceManager* mgr, + nsIRDFDataBase* db, + nsIRDFNode* resource) +{ + PRBool result = PR_FALSE; + + nsIRDFNode* RDF_instanceOf = NULL; + nsIRDFNode* RDF_Bag = NULL; + + nsresult rv; + if (NS_FAILED(rv = mgr->GetNode(kURIRDF_instanceOf, RDF_instanceOf))) + goto done; + + if (NS_FAILED(rv = mgr->GetNode(kURIRDF_Bag, RDF_Bag))) + goto done; + + rv = db->HasAssertion(resource, RDF_instanceOf, RDF_Bag, PR_TRUE, result); + +done: + NS_IF_RELEASE(RDF_Bag); + NS_IF_RELEASE(RDF_instanceOf); + return result; +} + + +// A complete hack that looks at the string value of a node and +// guesses if it's a resource +static PRBool +rdf_IsResource(nsIRDFNode* node) +{ + nsresult rv; + nsAutoString v; + + if (NS_FAILED(rv = node->GetStringValue(v))) + return PR_FALSE; + + PRInt32 index; + + // A URI needs a colon. + index = v.Find(':'); + if (index < 0) + return PR_FALSE; + + // Assume some sane maximum for protocol specs +#define MAX_PROTOCOL_SPEC 10 + if (index > MAX_PROTOCOL_SPEC) + return PR_FALSE; + + // It can't have spaces or newlines or tabs + if (v.Find(' ') > 0 || v.Find('\n') > 0 || v.Find('\t') > 0) + return PR_FALSE; + + return PR_TRUE; +} + + + +//////////////////////////////////////////////////////////////////////// +// RDFDOMNodeListImpl +// +// Helper class to implement the nsIDOMNodeList interface. It's +// probably wrong in some sense, as it uses the "naked" content +// interface to look for kids. (I assume in general this is bad +// because there may be pseudo-elements created for presentation +// that aren't visible to the DOM.) +// + +class RDFDOMNodeListImpl : public nsIDOMNodeList { +private: + nsRDFElement* mElement; + +public: + RDFDOMNodeListImpl(nsRDFElement* element) : mElement(element) { + NS_IF_ADDREF(mElement); + } + + virtual ~RDFDOMNodeListImpl(void) { + NS_IF_RELEASE(mElement); + } + + // nsISupports interface + NS_DECL_ISUPPORTS + + NS_DECL_IDOMNODELIST +}; + +NS_IMPL_ISUPPORTS(RDFDOMNodeListImpl, kIDOMNodeListIID); + +NS_IMETHODIMP +RDFDOMNodeListImpl::GetLength(PRUint32* aLength) +{ + PRInt32 count; + nsresult rv; + if (NS_FAILED(rv = mElement->ChildCount(count))) + return rv; + *aLength = count; + return NS_OK; +} + + +NS_IMETHODIMP +RDFDOMNodeListImpl::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + // XXX naive. probably breaks when there are pseudo elements or something. + nsresult rv; + nsIContent* contentChild; + if (NS_FAILED(rv = mElement->ChildAt(aIndex, contentChild))) + return rv; + + rv = contentChild->QueryInterface(kIDOMNodeIID, (void**) aReturn); + NS_RELEASE(contentChild); + + return rv; +} + +//////////////////////////////////////////////////////////////////////// +// nsRDFElement + +nsresult +NS_NewRDFElement(nsIRDFContent** result) +{ + NS_PRECONDITION(result, "null ptr"); + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = static_cast(new nsRDFElement()); + if (! *result) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(*result); + return NS_OK; +} + +nsRDFElement::nsRDFElement(void) + : mDocument(nsnull), + mNameSpace(nsnull), + mNameSpaceId(gNameSpaceId_Unknown), + mScriptObject(nsnull), + mResource(nsnull), + mChildren(nsnull), + mParent(nsnull) +{ + NS_INIT_REFCNT(); +} + +nsRDFElement::~nsRDFElement() +{ + NS_IF_RELEASE(mNameSpace); + NS_IF_RELEASE(mResource); +} + +NS_IMPL_ADDREF(nsRDFElement); +NS_IMPL_RELEASE(nsRDFElement); + +NS_IMETHODIMP +nsRDFElement::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + if (iid.Equals(kIRDFContentIID) || + iid.Equals(kIXMLContentIID) || + iid.Equals(kIContentIID) || + iid.Equals(kISupportsIID)) { + *result = static_cast(this); + } + else if (iid.Equals(kIDOMElementIID) || + iid.Equals(kIDOMNodeIID)) { + *result = static_cast(this); + } + else if (iid.Equals(kIScriptObjectOwnerIID)) { + *result = static_cast(this); + } + else if (iid.Equals(kIDOMEventReceiverIID)) { + *result = static_cast(this); + } + else if (iid.Equals(kIJSScriptObjectIID)) { + *result = static_cast(this); + } + else { + *result = NULL; + return NS_NOINTERFACE; + } + + // if we get here, we know one of the above IIDs was ok. + AddRef(); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// nsIDOMNode interface + +NS_IMETHODIMP +nsRDFElement::GetNodeName(nsString& aNodeName) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetNodeValue(nsString& aNodeValue) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::SetNodeValue(const nsString& aNodeValue) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetNodeType(PRUint16* aNodeType) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetParentNode(nsIDOMNode** aParentNode) +{ + if (!mParent) + return NS_ERROR_NOT_INITIALIZED; + + return mParent->QueryInterface(kIDOMNodeIID, (void**) aParentNode); +} + + +NS_IMETHODIMP +nsRDFElement::GetChildNodes(nsIDOMNodeList** aChildNodes) +{ + nsresult rv; + if (!mChildren) { + if (NS_FAILED(rv = GenerateChildren())) + return rv; + } + + RDFDOMNodeListImpl* list = new RDFDOMNodeListImpl(this); + if (! list) + return NS_ERROR_OUT_OF_MEMORY; + + return list->QueryInterface(kIDOMNodeListIID, (void**) aChildNodes); +} + + +NS_IMETHODIMP +nsRDFElement::GetFirstChild(nsIDOMNode** aFirstChild) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetLastChild(nsIDOMNode** aLastChild) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetPreviousSibling(nsIDOMNode** aPreviousSibling) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetNextSibling(nsIDOMNode** aNextSibling) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetAttributes(nsIDOMNamedNodeMap** aAttributes) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetOwnerDocument(nsIDOMDocument** aOwnerDocument) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::InsertBefore(nsIDOMNode* aNewChild, nsIDOMNode* aRefChild, nsIDOMNode** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::ReplaceChild(nsIDOMNode* aNewChild, nsIDOMNode* aOldChild, nsIDOMNode** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::RemoveChild(nsIDOMNode* aOldChild, nsIDOMNode** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::AppendChild(nsIDOMNode* aNewChild, nsIDOMNode** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::HasChildNodes(PRBool* aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::CloneNode(PRBool aDeep, nsIDOMNode** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; + +#if 0 + nsRDFElement* it = new nsRDFElement(); + if (! it) + return NS_ERROR_OUT_OF_MEMORY; + + return it->QueryInterface(kIDOMNodeIID, (void**) aReturn); +#endif +} + + +//////////////////////////////////////////////////////////////////////// +// nsIDOMElement interface + +NS_IMETHODIMP +nsRDFElement::GetTagName(nsString& aTagName) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetDOMAttribute(const nsString& aName, nsString& aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::SetDOMAttribute(const nsString& aName, const nsString& aValue) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::RemoveAttribute(const nsString& aName) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetAttributeNode(const nsString& aName, nsIDOMAttr** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::SetAttributeNode(nsIDOMAttr* aNewAttr, nsIDOMAttr** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::RemoveAttributeNode(nsIDOMAttr* aOldAttr, nsIDOMAttr** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetElementsByTagName(const nsString& aName, nsIDOMNodeList** aReturn) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP +nsRDFElement::Normalize() +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +//////////////////////////////////////////////////////////////////////// +// nsIDOMEventReceiver interface + +NS_IMETHODIMP +nsRDFElement::AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::GetListenerManager(nsIEventListenerManager** aInstancePtrResult) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +//////////////////////////////////////////////////////////////////////// +// nsIScriptObjectOwner interface + +NS_IMETHODIMP +nsRDFElement::GetScriptObject(nsIScriptContext* aContext, void** aScriptObject) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::SetScriptObject(void *aScriptObject) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +//////////////////////////////////////////////////////////////////////// +// nsIJSScriptObject interface + +PRBool +nsRDFElement::AddProperty(JSContext *aContext, jsval aID, jsval *aVp) +{ + return PR_FALSE; +} + +PRBool +nsRDFElement::DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp) +{ + return PR_FALSE; +} + +PRBool +nsRDFElement::GetProperty(JSContext *aContext, jsval aID, jsval *aVp) +{ + return PR_FALSE; +} + +PRBool +nsRDFElement::SetProperty(JSContext *aContext, jsval aID, jsval *aVp) +{ + return PR_FALSE; +} + +PRBool +nsRDFElement::EnumerateProperty(JSContext *aContext) +{ + return PR_FALSE; +} + + +PRBool +nsRDFElement::Resolve(JSContext *aContext, jsval aID) +{ + return PR_FALSE; +} + + +PRBool +nsRDFElement::Convert(JSContext *aContext, jsval aID) +{ + return PR_FALSE; +} + + +void +nsRDFElement::Finalize(JSContext *aContext) +{ +} + + + +//////////////////////////////////////////////////////////////////////// +// nsIConent interface + +NS_IMETHODIMP +nsRDFElement::GetDocument(nsIDocument*& aResult) const +{ + nsIDocument* doc; + nsresult rv = mDocument->QueryInterface(kIDocumentIID, (void**) &doc); + aResult = doc; // implicit AddRef() from QI + return rv; +} + +NS_IMETHODIMP +nsRDFElement::SetDocument(nsIDocument* aDocument, PRBool aDeep) +{ + NS_IF_RELEASE(mDocument); + + nsresult rv; + + if (aDocument) { + if (NS_FAILED(rv = aDocument->QueryInterface(kIRDFDocumentIID, + (void**) &mDocument))) + return rv; + } + + // implicit AddRef() from QI + + if (aDeep && mChildren) { + for (PRInt32 i = mChildren->Count() - 1; i >= 0; --i) { + // XXX this entire block could be more rigorous about + // dealing with failure. + nsISupports* obj = mChildren->ElementAt(i); + + PR_ASSERT(obj); + if (! obj) + continue; + + nsIContent* child; + if (NS_SUCCEEDED(obj->QueryInterface(kIContentIID, (void**) &child))) { + child->SetDocument(aDocument, aDeep); + NS_RELEASE(child); + } + + NS_RELEASE(obj); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::GetParent(nsIContent*& aResult) const +{ + if (!mParent) + return NS_ERROR_NOT_INITIALIZED; + + aResult = mParent; + NS_ADDREF(aResult); + + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::SetParent(nsIContent* aParent) +{ + // XXX don't allow modification of parents through this interface method? + PR_ASSERT(! mParent); + if (mParent) + return NS_ERROR_ALREADY_INITIALIZED; + + PR_ASSERT(aParent); + if (!aParent) + return NS_ERROR_NULL_POINTER; + + mParent = aParent; + NS_IF_ADDREF(mParent); + + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::CanContainChildren(PRBool& aResult) const +{ + aResult = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::ChildCount(PRInt32& aResult) const +{ + nsresult rv; + if (!mChildren) { + if (NS_FAILED(rv = GenerateChildren())) + return rv; + } + + aResult = mChildren->Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::ChildAt(PRInt32 aIndex, nsIContent*& aResult) const +{ + nsresult rv; + if (!mChildren) { + if (NS_FAILED(rv = GenerateChildren())) + return rv; + } + + nsISupports* obj = mChildren->ElementAt(aIndex); + nsIContent* content; + rv = obj->QueryInterface(kIContentIID, (void**) &content); + obj->Release(); + + aResult = content; + return rv; +} + +NS_IMETHODIMP +nsRDFElement::IndexOf(nsIContent* aPossibleChild, PRInt32& aResult) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsRDFElement::ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsRDFElement::AppendChildTo(nsIContent* aKid, PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsRDFElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsRDFElement::IsSynthetic(PRBool& aResult) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::GetTag(nsIAtom*& aResult) const +{ + PR_ASSERT(mResource); + if (! mResource) + return NS_ERROR_NOT_INITIALIZED; + + // XXX the problem with this is that we only have a + // fully-qualified URI, not "just" the tag. And I think the style + // system ain't gonna work right with that. So this is a complete + // hack to parse what probably _was_ the tag out. + nsresult rv; + + nsAutoString s; + if (NS_FAILED(rv = mResource->GetStringValue(s))) + return rv; + + PRInt32 index; + + if ((index = s.RFind('#')) >= 0) + s.Cut(0, index + 1); + else if ((index = s.RFind('/')) >= 0) + s.Cut(0, index + 1); + + s.ToUpperCase(); // because that's how CSS works + + aResult = NS_NewAtom(s); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFElement::SetAttribute(const nsString& aName, + const nsString& aValue, + PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + + +NS_IMETHODIMP +nsRDFElement::GetAttribute(const nsString& aName, nsString& aResult) const +{ + nsresult rv; + nsIRDFResourceManager* mgr = NULL; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + nsIRDFDataBase* db = NULL; + nsIRDFNode* property = NULL; + nsIRDFNode* value = NULL; + + if (NS_FAILED(rv = mDocument->GetDataBase(db))) + goto done; + + if (NS_FAILED(rv = mgr->GetNode(aName, property))) + goto done; + + // XXX Only returns the first value. yer screwed for + // multi-attributes, I guess. + + if (NS_FAILED(rv = db->GetTarget(mResource, property, PR_TRUE, value))) + goto done; + + rv = value->GetStringValue(aResult); + +done: + NS_IF_RELEASE(property); + NS_IF_RELEASE(value); + NS_IF_RELEASE(db); + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + + return rv; +} + +NS_IMETHODIMP +nsRDFElement::UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify) +{ + PR_ASSERT(0); // this should be done via RDF + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsRDFElement::GetAllAttributeNames(nsISupportsArray* aArray, PRInt32& aResult) const +{ + if (! aArray) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + nsIRDFResourceManager* mgr = NULL; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + nsIRDFDataBase* db = NULL; + nsIRDFCursor* properties = NULL; + PRBool moreProperties; + + if (NS_FAILED(rv = mDocument->GetDataBase(db))) + goto done; + + if (NS_FAILED(rv = db->ArcLabelsOut(mResource, properties))) + goto done; + + aArray->Clear(); // XXX or did you want me to append? + aResult = 0; + + while (NS_SUCCEEDED(rv = properties->HasMoreElements(moreProperties)) && moreProperties) { + nsIRDFNode* property = NULL; + PRBool tv; + + if (NS_FAILED(rv = properties->GetNext(property, tv /* ignored */))) + break; + + nsAutoString uri; + if (NS_SUCCEEDED(rv = property->GetStringValue(uri))) { + nsIAtom* atom = NS_NewAtom(uri); + if (atom) { + aArray->AppendElement(atom); + ++aResult; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + + NS_RELEASE(property); + + if (NS_FAILED(rv)) + break; + } + +done: + NS_IF_RELEASE(properties); + NS_IF_RELEASE(db); + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + + return rv; +} + +NS_IMETHODIMP +nsRDFElement::GetAttributeCount(PRInt32& aResult) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +static void +rdf_Indent(FILE* out, PRInt32 aIndent) +{ + for (PRInt32 i = aIndent; --i >= 0; ) fputs(" ", out); +} + +NS_IMETHODIMP +nsRDFElement::List(FILE* out, PRInt32 aIndent) const +{ + if (! mResource) + return NS_ERROR_NOT_INITIALIZED; + + nsresult rv; + + { + nsIAtom* tag; + if (NS_FAILED(rv = GetTag(tag))) + return rv; + + rdf_Indent(out, aIndent); + fputs("[RDF ", out); + fputs(tag->GetUnicode(), out); + fputs("\n", out); + + NS_RELEASE(tag); + } + + { + nsISupportsArray* attrs; + PRInt32 nattrs; + + if (NS_FAILED(rv = NS_NewISupportsArray(&attrs))) + return rv; + + if (NS_SUCCEEDED(rv = GetAllAttributeNames(attrs, nattrs))) { + for (PRInt32 i = 0; i < nattrs; ++i) { + nsIAtom* attr = (nsIAtom*) attrs->ElementAt(i); + + nsAutoString s; + attr->ToString(s); + NS_RELEASE(attr); + + nsAutoString v; + GetAttribute(s, v); + + rdf_Indent(out, aIndent); + fputs(" ", out); + fputs(s, out); + fputs("=", out); + fputs(v, out); + fputs("\n", out); + } + } + + NS_RELEASE(attrs); + + if (NS_FAILED(rv)) + return rv; + } + + rdf_Indent(out, aIndent); + fputs("]\n", out); + + { + PRInt32 nchildren; + if (NS_FAILED(rv = ChildCount(nchildren))) + return rv; + + for (PRInt32 i = 0; i < nchildren; ++i) { + nsIContent* child; + if (NS_FAILED(rv = ChildAt(i, child))) + return rv; + + rv = child->List(out, aIndent + 1); + NS_RELEASE(child); + + if (NS_FAILED(rv)) + return rv; + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::BeginConvertToXIF(nsXIFConverter& aConverter) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::ConvertContentToXIF(nsXIFConverter& aConverter) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::FinishConvertToXIF(nsXIFConverter& aConverter) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsRDFElement::SizeOf(nsISizeOfHandler* aHandler) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + + +NS_IMETHODIMP +nsRDFElement::HandleDOMEvent(nsIPresContext& aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus& aEventStatus) +{ + return NS_OK; +} + + +//////////////////////////////////////////////////////////////////////// +// nsIXMLContent + +NS_IMETHODIMP +nsRDFElement::SetNameSpace(nsIAtom* aNameSpace) +{ + NS_IF_RELEASE(mNameSpace); + mNameSpace = aNameSpace; + NS_IF_ADDREF(mNameSpace); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::GetNameSpace(nsIAtom*& aNameSpace) +{ + aNameSpace = mNameSpace; + NS_IF_ADDREF(mNameSpace); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::SetNameSpaceIdentifier(PRInt32 aNameSpaceId) +{ + mNameSpaceId = aNameSpaceId; + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::GetNameSpaceIdentifier(PRInt32& aNameSpaceId) +{ + aNameSpaceId = mNameSpaceId; + return NS_OK; +} + + +//////////////////////////////////////////////////////////////////////// +// nsIRDFContent + +NS_IMETHODIMP +nsRDFElement::SetResource(const nsString& aURI) +{ + if (mResource) + return NS_ERROR_ALREADY_INITIALIZED; + + nsresult rv; + + nsIRDFResourceManager* mgr = NULL; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + rv = mgr->GetNode(aURI, mResource); // implicit AddRef() + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + + return rv; +} + +NS_IMETHODIMP +nsRDFElement::GetResource(nsString& rURI) const +{ + if (! mResource) + return NS_ERROR_NOT_INITIALIZED; + + return mResource->GetStringValue(rURI); + return NS_OK; +} + +NS_IMETHODIMP +nsRDFElement::SetProperty(const nsString& aPropertyURI, const nsString& aValue) +{ + if (!mResource || !mDocument) + return NS_ERROR_NOT_INITIALIZED; + + nsString resource; + mResource->GetStringValue(resource); + +#ifdef DEBUG_waterson + char buf[256]; + printf("assert [\n"); + printf(" %s\n", resource.ToCString(buf, sizeof(buf))); + printf(" %s\n", aPropertyURI.ToCString(buf, sizeof(buf))); + printf(" %s\n", aValue.ToCString(buf, sizeof(buf))); + printf("]\n"); +#endif + + nsresult rv; + nsIRDFResourceManager* mgr = NULL; + + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + nsIRDFNode* property = NULL; + nsIRDFNode* value = NULL; + nsIRDFDataBase* db = NULL; + + if (NS_FAILED(rv = mgr->GetNode(aPropertyURI, property))) + goto done; + + if (NS_FAILED(rv = mgr->GetNode(aValue, value))) + goto done; + + if (NS_FAILED(rv = mDocument->GetDataBase(db))) + goto done; + + rv = db->Assert(mResource, property, value, PR_TRUE); + +done: + NS_IF_RELEASE(db); + NS_IF_RELEASE(value); + NS_IF_RELEASE(property); + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + + return rv; +} + +NS_IMETHODIMP +nsRDFElement::GetProperty(const nsString& aPropertyURI, nsString& rValue) const +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + + +//////////////////////////////////////////////////////////////////////// +// Implementation methods + + +// GenerateChildren +// +// This is the money, baby. It's where we do the work of traversing +// the RDF graph to produce new nsRDFElements and hook them up into +// a semblance of a content model. +// +// Ideally, this would be a "strategy", along with the logic for +// manipulating the generated content. (Well, actually, ideally, +// this would be hard coded to produce one kind of tree, and XSL +// would do the work of transforming it for presentation.) +// +nsresult +nsRDFElement::GenerateChildren(void) const +{ + nsresult rv; + + if (!mResource || !mDocument) + return NS_ERROR_NOT_INITIALIZED; + + if (! mChildren) { + if (NS_FAILED(rv = NS_NewISupportsArray(&mChildren))) + return rv; + } + else { + mChildren->Clear(); + } + + nsIRDFResourceManager* mgr; + if (NS_FAILED(rv = nsServiceManager::GetService(kRDFResourceManagerCID, + kIRDFResourceManagerIID, + (nsISupports**) &mgr))) + return rv; + + nsIRDFDataBase* db = NULL; + nsIRDFCursor* properties = NULL; + PRBool moreProperties; + + if (NS_FAILED(rv = mDocument->GetDataBase(db))) + goto done; + +#ifdef ONLY_CREATE_RDF_CONTAINERS_AS_CONTENT + if (! rdf_IsContainer(mgr, db, mResource)) + goto done; +#endif + + // Create a cursor that'll enumerate all of the outbound arcs + if (NS_FAILED(rv = db->ArcLabelsOut(mResource, properties))) + goto done; + + while (NS_SUCCEEDED(rv = properties->HasMoreElements(moreProperties)) && moreProperties) { + nsIRDFNode* property = NULL; + PRBool tv; + + if (NS_FAILED(rv = properties->GetNext(property, tv /* ignored */))) + break; + + nsAutoString uri; + if (NS_FAILED(rv = property->GetStringValue(uri))) { + NS_RELEASE(property); + break; + } + +#ifdef ONLY_CREATE_RDF_CONTAINERS_AS_CONTENT + if (! rdf_IsOrdinalProperty(uri)) { + NS_RELEASE(property); + continue; + } +#endif + + // Create a second cursor that'll enumerate all of the values + // for all of the arcs. + nsIRDFCursor* values; + if (NS_FAILED(rv = db->GetTargets(mResource, property, PR_TRUE, values))) { + NS_RELEASE(property); + break; + } + + PRBool moreValues; + while (NS_SUCCEEDED(rv = values->HasMoreElements(moreValues)) && moreValues) { + nsIRDFNode* value = NULL; + if (NS_FAILED(rv = values->GetNext(value, tv /* ignored */))) + break; + + // XXX At this point, we need to decide exactly what kind + // of kid to create in the content model. For example, for + // leaf nodes, we probably want to create some kind of + // text element. + nsIRDFContent* child; + if (NS_FAILED(rv = CreateChild(property, value, child))) { + NS_RELEASE(value); + break; + } + + // And finally, add the child into the content model + mChildren->AppendElement(child); + + NS_RELEASE(child); + NS_RELEASE(value); + } + + NS_RELEASE(values); + NS_RELEASE(property); + + if (NS_FAILED(rv)) + break; + } + +done: + NS_IF_RELEASE(properties); + NS_IF_RELEASE(db); + nsServiceManager::ReleaseService(kRDFResourceManagerCID, mgr); + + return rv; +} + + + +nsresult +nsRDFElement::CreateChild(nsIRDFNode* value, + nsIRDFContent*& result) const +{ + // XXX I wish that we could avoid doing it "by hand" like this + // (i.e., use interface methods so that we could extend to other + // kinds of kids later); however, there is a cascade of const-ness + // out to things like ChildCount() that is tough to get around. + + nsRDFElement* child = new nsRDFElement(); + if (! child) + return NS_ERROR_OUT_OF_MEMORY; + + child->mDocument = mDocument; + NS_ADDREF(child->mDocument); + + child->mResource = value; + NS_ADDREF(child->mResource); + + child->mParent = static_cast(const_cast(this)); + NS_ADDREF(child->mParent); + + result = child; + NS_ADDREF(result); + + return NS_OK; +} + + +nsresult +nsRDFElement::CreateChild(nsIRDFNode* property, + nsIRDFNode* value, + nsIRDFContent*& result) const +{ + nsresult rv; + nsRDFElement* child = NULL; + nsRDFElement* grandchild = NULL; + nsIHTMLContent* grandchild2 = NULL; // XXX should just be regular nsIContent + nsITextContent* text = NULL; + nsIDocument* doc = NULL; + nsAutoString v; + + child = new nsRDFElement(); + if (! child) { + return NS_ERROR_OUT_OF_MEMORY; + goto error; + } + + NS_ADDREF(child); + child->mDocument = mDocument; + child->mResource = property; + child->mParent = static_cast(const_cast(this)); + + NS_ADDREF(child->mDocument); + NS_ADDREF(child->mResource); + NS_ADDREF(child->mParent); + + if (NS_FAILED(rv = NS_NewISupportsArray(&child->mChildren))) + goto error; + + // If this is NOT a resource, then construct a grandchild which is + // just a vanilla text node. + if (! rdf_IsResource(value)) { + if (NS_FAILED(rv = value->GetStringValue(v))) + goto error; + + if (NS_FAILED(rv = NS_NewTextNode(&grandchild2))) + goto error; + + if (NS_FAILED(rv = mDocument->QueryInterface(kIDocumentIID, (void**) &doc))) + goto error; + + if (NS_FAILED(rv = grandchild2->SetDocument(doc, PR_FALSE))) + goto error; + + NS_RELEASE(doc); + + if (NS_FAILED(rv = grandchild2->QueryInterface(kITextContentIID, (void**) &text))) + goto error; + + if (NS_FAILED(rv = text->SetText(v.GetUnicode(), v.Length(), PR_FALSE))) + goto error; + + NS_RELEASE(text); + + // hook it up to the child + if (NS_FAILED(rv = grandchild2->SetParent(child))) + goto error; + + child->mChildren->AppendElement(static_cast(grandchild2)); + } + + // Construct a grandchild which is another RDF node. + grandchild = new nsRDFElement(); + if (! grandchild) { + rv = NS_ERROR_OUT_OF_MEMORY; + goto error; + } + + grandchild->mDocument = mDocument; + grandchild->mResource = value; + grandchild->mParent = static_cast(const_cast(child)); + + NS_ADDREF(grandchild->mDocument); + NS_ADDREF(grandchild->mResource); + NS_ADDREF(grandchild->mParent); + + child->mChildren->AppendElement(static_cast(grandchild)); + + // whew! + result = child; + return NS_OK; + +error: + NS_IF_RELEASE(text); + NS_IF_RELEASE(doc); + NS_IF_RELEASE(grandchild); + NS_IF_RELEASE(child); + return rv; +} + + diff --git a/rdf/src/nsRDFElement.h b/rdf/src/nsRDFElement.h new file mode 100644 index 000000000000..fe32b63c34ad --- /dev/null +++ b/rdf/src/nsRDFElement.h @@ -0,0 +1,140 @@ +/* -*- 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. + */ + +#ifndef nsRDFElement_h___ +#define nsRDFElement_h___ + +#include "nsIDOMElement.h" +#include "nsIScriptObjectOwner.h" +#include "nsIDOMEventReceiver.h" +#include "nsIRDFContent.h" +#include "nsIJSScriptObject.h" + +class nsIContent; +class nsIRDFDocument; +class nsIAtom; +class nsIEventListenerManager; +class nsIHTMLAttributes; +class nsIRDFNode; +class nsISupportsArray; + +// XXX should we make this inheirit from the nsXMLElement +// implementation??? + +class nsRDFElement : public nsIDOMElement, + public nsIDOMEventReceiver, + public nsIScriptObjectOwner, + public nsIJSScriptObject, + public nsIRDFContent +{ +public: + nsRDFElement(void); + ~nsRDFElement(void); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIDOMNode (from nsIDOMElement) + NS_DECL_IDOMNODE + + // nsIDOMElement + NS_DECL_IDOMELEMENT + + // nsIScriptObjectOwner + NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void *aScriptObject); + + // nsIContent (from nsIRDFContent via nsIXMLContent) + NS_IMETHOD GetDocument(nsIDocument*& aResult) const; + NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep); + NS_IMETHOD GetParent(nsIContent*& aResult) const; + NS_IMETHOD SetParent(nsIContent* aParent); + NS_IMETHOD CanContainChildren(PRBool& aResult) const; + NS_IMETHOD ChildCount(PRInt32& aResult) const; + NS_IMETHOD ChildAt(PRInt32 aIndex, nsIContent*& aResult) const; + NS_IMETHOD IndexOf(nsIContent* aPossibleChild, PRInt32& aResult) const; + NS_IMETHOD InsertChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify); + NS_IMETHOD ReplaceChildAt(nsIContent* aKid, PRInt32 aIndex, PRBool aNotify); + NS_IMETHOD AppendChildTo(nsIContent* aKid, PRBool aNotify); + NS_IMETHOD RemoveChildAt(PRInt32 aIndex, PRBool aNotify); + NS_IMETHOD IsSynthetic(PRBool& aResult); + NS_IMETHOD GetTag(nsIAtom*& aResult) const; + NS_IMETHOD SetAttribute(const nsString& aName, const nsString& aValue, PRBool aNotify); + NS_IMETHOD GetAttribute(const nsString& aName, nsString& aResult) const; + NS_IMETHOD UnsetAttribute(nsIAtom* aAttribute, PRBool aNotify); + NS_IMETHOD GetAllAttributeNames(nsISupportsArray* aArray, PRInt32& aResult) const; + NS_IMETHOD GetAttributeCount(PRInt32& aResult) const; + NS_IMETHOD List(FILE* out, PRInt32 aIndent) const; + NS_IMETHOD BeginConvertToXIF(nsXIFConverter& aConverter) const; + NS_IMETHOD ConvertContentToXIF(nsXIFConverter& aConverter) const; + NS_IMETHOD FinishConvertToXIF(nsXIFConverter& aConverter) const; + NS_IMETHOD SizeOf(nsISizeOfHandler* aHandler) const; + NS_IMETHOD HandleDOMEvent(nsIPresContext& aPresContext, + nsEvent* aEvent, + nsIDOMEvent** aDOMEvent, + PRUint32 aFlags, + nsEventStatus& aEventStatus); + + // nsIXMLContent (from nsIRDFContent) + NS_IMETHOD SetNameSpace(nsIAtom* aNameSpace); + NS_IMETHOD GetNameSpace(nsIAtom*& aNameSpace); + NS_IMETHOD SetNameSpaceIdentifier(PRInt32 aNameSpaceId); + NS_IMETHOD GetNameSpaceIdentifier(PRInt32& aNameSpeceId); + + // nsIRDFContent + NS_IMETHOD SetResource(const nsString& aURI); + NS_IMETHOD GetResource(nsString& rURI) const; + + NS_IMETHOD SetProperty(const nsString& aPropertyURI, const nsString& aValue); + NS_IMETHOD GetProperty(const nsString& aPropertyURI, nsString& rValue) const; + + // nsIDOMEventReceiver + NS_IMETHOD AddEventListener(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD RemoveEventListener(nsIDOMEventListener *aListener, const nsIID& aIID); + NS_IMETHOD GetListenerManager(nsIEventListenerManager** aInstancePtrResult); + NS_IMETHOD GetNewListenerManager(nsIEventListenerManager **aInstancePtrResult); + + + // nsIJSScriptObject + virtual PRBool AddProperty(JSContext *aContext, jsval aID, jsval *aVp); + virtual PRBool DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp); + virtual PRBool GetProperty(JSContext *aContext, jsval aID, jsval *aVp); + virtual PRBool SetProperty(JSContext *aContext, jsval aID, jsval *aVp); + virtual PRBool EnumerateProperty(JSContext *aContext); + virtual PRBool Resolve(JSContext *aContext, jsval aID); + virtual PRBool Convert(JSContext *aContext, jsval aID); + virtual void Finalize(JSContext *aContext); + +protected: + nsIRDFDocument* mDocument; + nsIAtom* mNameSpace; + PRInt32 mNameSpaceId; + void* mScriptObject; + nsIRDFNode* mResource; + mutable nsISupportsArray* mChildren; + nsIContent* mParent; + + nsresult GenerateChildren(void) const; + nsresult CreateChild(nsIRDFNode* value, nsIRDFContent*& result) const; + nsresult CreateChild(nsIRDFNode* property, + nsIRDFNode* value, + nsIRDFContent*& result) const; +}; + +#endif // nsRDFElement_h___ diff --git a/rdf/src/nsRDFFactory.cpp b/rdf/src/nsRDFFactory.cpp index d59e24a44132..d23088116dff 100644 --- a/rdf/src/nsRDFFactory.cpp +++ b/rdf/src/nsRDFFactory.cpp @@ -18,29 +18,33 @@ #include "nsISupports.h" #include "nsIFactory.h" -#include "nsRDFTreeDataModel.h" -#include "nsRDFToolbarDataModel.h" +#include "nsRDFResourceManager.h" +#include "nsMemoryDataSource.h" +#include "nsBookmarkDataSource.h" +#include "nsSimpleDataBase.h" +#include "nsRDFDocument.h" +#include "nsRDFRegistryImpl.h" #include "nsRDFCID.h" static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); -static NS_DEFINE_CID(kRDFTreeDataModelCID, NS_RDFTREEDATAMODEL_CID); -static NS_DEFINE_CID(kRDFToolbarDataModelCID, NS_RDFTOOLBARDATAMODEL_CID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +static NS_DEFINE_CID(kRDFBookmarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID); +static NS_DEFINE_CID(kRDFMemoryDataSourceCID, NS_RDFMEMORYDATASOURCE_CID); +static NS_DEFINE_CID(kRDFRegistryCID, NS_RDFREGISTRY_CID); +static NS_DEFINE_CID(kRDFResourceManagerCID, NS_RDFRESOURCEMANAGER_CID); +static NS_DEFINE_CID(kRDFSimpleDataBaseCID, NS_RDFSIMPLEDATABASE_CID); +static NS_DEFINE_CID(kRDFDocumentCID, NS_RDFDOCUMENT_CID); class nsRDFFactory : public nsIFactory { public: nsRDFFactory(const nsCID &aClass); - //////////////////////////////////////// // nsISupports methods - // - NS_DECL_ISUPPORTS - //////////////////////////////////////// // nsIFactory methods - // NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult); @@ -107,11 +111,23 @@ nsRDFFactory::CreateInstance(nsISupports *aOuter, *aResult = NULL; nsISupports *inst = NULL; - if (mClassID.Equals(kRDFTreeDataModelCID)) { - inst = static_cast(new nsRDFTreeDataModel()); + if (mClassID.Equals(kRDFResourceManagerCID)) { + inst = static_cast(new nsRDFResourceManager()); } - else if (mClassID.Equals(kRDFToolbarDataModelCID)) { - inst = static_cast(new nsRDFToolbarDataModel()); + else if (mClassID.Equals(kRDFMemoryDataSourceCID)) { + inst = static_cast(new nsMemoryDataSource()); + } + else if (mClassID.Equals(kRDFBookmarkDataSourceCID)) { + inst = static_cast(new nsBookmarkDataSource()); + } + else if (mClassID.Equals(kRDFRegistryCID)) { + inst = static_cast(new nsRDFRegistryImpl()); + } + else if (mClassID.Equals(kRDFSimpleDataBaseCID)) { + inst = static_cast(new nsSimpleDataBase()); + } + else if (mClassID.Equals(kRDFDocumentCID)) { + inst = static_cast(new nsRDFDocument()); } if (! inst) @@ -131,18 +147,14 @@ nsresult nsRDFFactory::LockFactory(PRBool aLock) return NS_OK; } +//////////////////////////////////////////////////////////////////////// + + + // return the proper factory to the caller extern "C" PR_EXTERN(nsresult) NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) { - static PRBool gInitialized = PR_FALSE; - if (! gInitialized) { - gInitialized = PR_TRUE; - - // do one-time library initialization - RDF_Init(); - } - if (! aFactory) return NS_ERROR_NULL_POINTER; @@ -152,3 +164,4 @@ NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory); } + diff --git a/rdf/src/nsRDFRegistryImpl.cpp b/rdf/src/nsRDFRegistryImpl.cpp new file mode 100644 index 000000000000..b7c73f772200 --- /dev/null +++ b/rdf/src/nsRDFRegistryImpl.cpp @@ -0,0 +1,109 @@ +/* -*- 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 "nsIRDFDataSource.h" +#include "nsRDFRegistryImpl.h" +#include "nsString.h" +#include "prlog.h" + +static NS_DEFINE_IID(kIRDFRegistryIID, NS_IRDFREGISTRY_IID); + +//////////////////////////////////////////////////////////////////////// + +struct RegistryEntry { + nsAutoString mPrefix; + nsIRDFDataSource* mDataSource; +}; + +//////////////////////////////////////////////////////////////////////// + +nsRDFRegistryImpl::nsRDFRegistryImpl(void) +{ + NS_INIT_REFCNT(); +} + + +nsRDFRegistryImpl::~nsRDFRegistryImpl(void) +{ + PR_ASSERT(mDataSources.Count() == 0); +} + + +NS_IMPL_ISUPPORTS(nsRDFRegistryImpl, kIRDFRegistryIID); + +NS_IMETHODIMP +nsRDFRegistryImpl::Register(const nsString& prefix, + nsIRDFDataSource* dataSource) +{ + if (! dataSource) + return NS_ERROR_NULL_POINTER; + + // Make sure that we don't have duplicates, and that we don't try + // to replace an existing entry... + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + RegistryEntry* e = static_cast(mDataSources[i]); + if (e->mPrefix == prefix) + return NS_ERROR_FAILURE; + + // XXX not sure if this is right... + if (e->mDataSource == dataSource) + return NS_ERROR_FAILURE; + } + + RegistryEntry* e = new RegistryEntry; + if (! e) + return NS_ERROR_OUT_OF_MEMORY; + + e->mPrefix = prefix; + e->mDataSource = dataSource; // n.b., no AddRef()! + + mDataSources.AppendElement(e); + return NS_OK; +} + + +NS_IMETHODIMP +nsRDFRegistryImpl::Unregister(const nsIRDFDataSource* dataSource) +{ + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + RegistryEntry* e = static_cast(mDataSources[i]); + if (e->mDataSource == dataSource) { + mDataSources.RemoveElementAt(i); + delete e; + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} + + +NS_IMETHODIMP +nsRDFRegistryImpl::Find(const nsString& uri, nsIRDFDataSource*& result) +{ + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + RegistryEntry* e = static_cast(mDataSources[i]); + if (uri.Find(e->mPrefix) == 0) { + result = e->mDataSource; + NS_ADDREF(result); + return NS_OK; + } + } + + return NS_ERROR_FAILURE; +} diff --git a/rdf/src/nsRDFRegistryImpl.h b/rdf/src/nsRDFRegistryImpl.h new file mode 100644 index 000000000000..4009e0b19bc2 --- /dev/null +++ b/rdf/src/nsRDFRegistryImpl.h @@ -0,0 +1,42 @@ +/* -*- 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. + */ + +#ifndef nsRDFRegistryImpl_h__ +#define nsRDFRegistryImpl_h__ + +#include "nsIRDFRegistry.h" +#include "nsVoidArray.h" + +class nsRDFRegistryImpl : public nsIRDFRegistry { +protected: + nsVoidArray mDataSources; + ~nsRDFRegistryImpl(void); + +public: + nsRDFRegistryImpl(void); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIRDFRegistry interface + NS_IMETHOD Register(const nsString& prefix, nsIRDFDataSource* dataSource); + NS_IMETHOD Unregister(const nsIRDFDataSource* dataSource); + NS_IMETHOD Find(const nsString& uri, nsIRDFDataSource*& result); +}; + +#endif // nsRDFRegistryImpl_h__ diff --git a/rdf/src/nsRDFResourceManager.cpp b/rdf/src/nsRDFResourceManager.cpp new file mode 100644 index 000000000000..204ed66bde1f --- /dev/null +++ b/rdf/src/nsRDFResourceManager.cpp @@ -0,0 +1,177 @@ +/* -*- 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 "nsIRDFNode.h" +#include "nsRDFResourceManager.h" +#include "nsString.h" +#include "nsIAtom.h" + +static NS_DEFINE_IID(kIRDFResourceManagerIID, NS_IRDFRESOURCEMANAGER_IID); + +//////////////////////////////////////////////////////////////////////// + +class RDFNodeImpl : public nsIRDFNode { +public: + RDFNodeImpl(nsRDFResourceManager* mgr, nsIAtom* value); + virtual ~RDFNodeImpl(void); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIRDFNode + NS_IMETHOD GetStringValue(nsString& value) const; + + NS_IMETHOD GetAtomValue(nsIAtom*& value) const; + + +private: + nsIAtom* mValue; + nsRDFResourceManager* mMgr; +}; + + +RDFNodeImpl::RDFNodeImpl(nsRDFResourceManager* mgr, nsIAtom* value) + : mMgr(mgr), mValue(value) +{ + NS_INIT_REFCNT(); + NS_IF_ADDREF(mValue); + NS_IF_ADDREF(mMgr); +} + + +RDFNodeImpl::~RDFNodeImpl(void) +{ + mMgr->ReleaseNode(this); + NS_IF_RELEASE(mValue); + NS_IF_RELEASE(mMgr); +} + + +static NS_DEFINE_IID(kIRDFNodeIID, NS_IRDFNODE_IID); +NS_IMPL_ISUPPORTS(RDFNodeImpl, kIRDFNodeIID); + +NS_IMETHODIMP +RDFNodeImpl::GetStringValue(nsString& value) const +{ + mValue->ToString(value); + return NS_OK; +} + +NS_IMETHODIMP +RDFNodeImpl::GetAtomValue(nsIAtom*& value) const +{ + value = mValue; + value->AddRef(); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// ResourceHashKey + +class ResourceHashKey : public nsHashKey +{ +private: + nsIAtom* mResource; + +public: + ResourceHashKey(nsIAtom* resource) : mResource(resource) { + NS_IF_ADDREF(mResource); + } + + virtual ~ResourceHashKey(void) { + NS_IF_RELEASE(mResource); + } + + // nsHashKey pure virtual interface methods + virtual PRUint32 HashValue(void) const { + return (PRUint32) mResource; + } + + virtual PRBool Equals(const nsHashKey* aKey) const { + ResourceHashKey* that; + + //if (! (that = dynamic_cast(aKey))) + if (! (that = (ResourceHashKey*)(aKey))) + return PR_FALSE; + + return (that->mResource == this->mResource); + } + + virtual nsHashKey* Clone(void) const { + return new ResourceHashKey(mResource); + } +}; + + +//////////////////////////////////////////////////////////////////////// +// nsRDFResourceManager + +nsRDFResourceManager::nsRDFResourceManager(void) +{ + NS_INIT_REFCNT(); +} + + +nsRDFResourceManager::~nsRDFResourceManager(void) +{ + // XXX LEAK! Make sure you release the nodes! +} + + +NS_IMPL_ISUPPORTS(nsRDFResourceManager, kIRDFResourceManagerIID); + + +NS_IMETHODIMP +nsRDFResourceManager::GetNode(const nsString& uri, nsIRDFNode*& resource) +{ + nsIAtom* atom = NS_NewAtom(uri); + if (!atom) + return NS_ERROR_OUT_OF_MEMORY; + + ResourceHashKey key(atom); + + resource = static_cast(mResources.Get(&key)); + if (! resource) { + resource = new RDFNodeImpl(this, atom); + if (resource) + mResources.Put(&key, resource); + + // We don't AddRef() the resource. + } + + atom->Release(); + + if (! resource) + return NS_ERROR_OUT_OF_MEMORY; + + resource->AddRef(); + return NS_OK; +} + + +void +nsRDFResourceManager::ReleaseNode(const RDFNodeImpl* resource) +{ + nsIAtom* atom; + resource->GetAtomValue(atom); + ResourceHashKey key(atom); + atom->Release(); + + mResources.Remove(&key); +} diff --git a/rdf/src/nsRDFResourceManager.h b/rdf/src/nsRDFResourceManager.h new file mode 100644 index 000000000000..b489d47e4d41 --- /dev/null +++ b/rdf/src/nsRDFResourceManager.h @@ -0,0 +1,46 @@ +/* -*- 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. + */ + +#ifndef nsRDFResourceManager_h__ +#define nsRDFResourceManager_h__ +#include "nsIRDFResourceManager.h" +#include "nsHashtable.h" + +class nsString; +class nsIRDFNode; +class RDFNodeImpl; + +class nsRDFResourceManager : public nsIRDFResourceManager { +protected: + nsHashtable mResources; + virtual ~nsRDFResourceManager(void); + +public: + nsRDFResourceManager(void); + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIRDFResourceManager + NS_IMETHOD GetNode(const nsString& uri, nsIRDFNode*& resource); + + void ReleaseNode(const RDFNodeImpl* resource); +}; + + +#endif // nsRDFResourceManager_h__ diff --git a/rdf/src/nsRDFToolbarDataModel.cpp b/rdf/src/nsRDFToolbarDataModel.cpp deleted file mode 100644 index 6c00fec0b9d5..000000000000 --- a/rdf/src/nsRDFToolbarDataModel.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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 "nsRDFToolbarDataModel.h" -#include "nsRDFToolbarDataModelItem.h" - -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); -static NS_DEFINE_IID(kIToolbarDataModelIID, NS_ITOOLBARDATAMODEL_IID); - - -//////////////////////////////////////////////////////////////////////// - -nsRDFToolbarDataModel::nsRDFToolbarDataModel(void) -{ - NS_INIT_REFCNT(); -} - - - -nsRDFToolbarDataModel::~nsRDFToolbarDataModel(void) -{ -} - -NS_IMETHODIMP_(nsrefcnt) -nsRDFToolbarDataModel::AddRef(void) -{ - return nsRDFDataModel::AddRef(); // delegate to the superclass -} - -NS_IMETHODIMP_(nsrefcnt) -nsRDFToolbarDataModel::Release(void) -{ - return nsRDFDataModel::Release(); // delegate to the superclass -} - -NS_IMETHODIMP -nsRDFToolbarDataModel::QueryInterface(const nsIID& iid, void** result) -{ - if (NULL == result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kIToolbarDataModelIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - // delegate to the superclass - return nsRDFDataModel::QueryInterface(iid, result); -} - -//////////////////////////////////////////////////////////////////////// -// nsIDataModel implementation -- delgates to superclass - -NS_IMETHODIMP -nsRDFToolbarDataModel::InitFromURL(const nsString& url) -{ - return nsRDFDataModel::InitFromURL(url); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModel::InitFromResource(nsIDMItem* pResource) -{ - return nsRDFDataModel::InitFromResource(pResource); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModel::GetDMWidget(nsIDMWidget*& widget) const -{ - return nsRDFDataModel::GetDMWidget(widget); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModel::SetDMWidget(nsIDMWidget* widget) -{ - return nsRDFDataModel::SetDMWidget(widget); -} - - - -NS_IMETHODIMP -nsRDFToolbarDataModel::GetStringPropertyValue(nsString& value, const nsString& property) const -{ - return nsRDFDataModel::GetStringPropertyValue(value, property); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModel::GetIntPropertyValue(PRInt32& value, const nsString& property) const -{ - return nsRDFDataModel::GetIntPropertyValue(value, property); -} - -//////////////////////////////////////////////////////////////////////// -// nsIToolbarDataModel interface - - - - -//////////////////////////////////////////////////////////////////////// -// Implementation methods - -NS_METHOD -nsRDFToolbarDataModel::CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) -{ - result = new nsRDFToolbarDataModelItem(*this, r); - if (! result) - return NS_ERROR_OUT_OF_MEMORY; - - result->AddRef(); // like a good little COM citizen - return NS_OK; -} diff --git a/rdf/src/nsRDFToolbarDataModel.h b/rdf/src/nsRDFToolbarDataModel.h deleted file mode 100644 index af64ceb1050f..000000000000 --- a/rdf/src/nsRDFToolbarDataModel.h +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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. - */ - -#ifndef nsRDFToolbarDataModel_h__ -#define nsRDFToolbarDataModel_h__ - -#include "nsRDFDataModel.h" -#include "nsIToolbarDataModel.h" -#include "rdf.h" - -//////////////////////////////////////////////////////////////////////// - -/** - * An implementation for the Toolbar widget model. - */ -class nsRDFToolbarDataModel : public nsIToolbarDataModel, public nsRDFDataModel { -public: - nsRDFToolbarDataModel(void); - virtual ~nsRDFToolbarDataModel(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface -- delegates to superclass - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - NS_IMETHOD QueryInterface(const nsIID& iid, void** result); - - //////////////////////////////////////////////////////////////////////// - // nsIDataModel interface -- delegates to superclass - - // Initializers - NS_IMETHOD InitFromURL(const nsString& url); - NS_IMETHOD InitFromResource(nsIDMItem* pResource); - - // Inspectors - NS_IMETHOD GetDMWidget(nsIDMWidget*& pWidget) const; - - // Setters - NS_IMETHOD SetDMWidget(nsIDMWidget* pWidget); - - // Methods to query the data model for property values for an entire widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& property) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& property) const; - - //////////////////////////////////////////////////////////////////////// - // nsIToolbarDataModel interface - - - //////////////////////////////////////////////////////////////////////// - // Implementation methods - - virtual NS_METHOD - CreateItem(RDF_Resource r, nsRDFDataModelItem*& result); - -private: -}; - - - -#endif // nsRDFToolbarDataModel_h__ diff --git a/rdf/src/nsRDFToolbarDataModelItem.cpp b/rdf/src/nsRDFToolbarDataModelItem.cpp deleted file mode 100644 index 5be0c88add20..000000000000 --- a/rdf/src/nsRDFToolbarDataModelItem.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- 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 "nsRDFToolbarDataModelItem.h" -#include "nsRDFToolbarDataModel.h" - -static NS_DEFINE_IID(kIToolbarDMItemIID, NS_ITOOLBARDMITEM_IID); -static NS_DEFINE_IID(kIDMItemIID, NS_ITOOLBARDMITEM_IID); -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); - -//////////////////////////////////////////////////////////////////////// - -nsRDFToolbarDataModelItem::nsRDFToolbarDataModelItem(nsRDFToolbarDataModel& toolbar, - RDF_Resource resource) - : nsRDFDataModelItem(toolbar, resource) -{ -} - - -nsRDFToolbarDataModelItem::~nsRDFToolbarDataModelItem(void) -{ -} - -NS_IMETHODIMP_(nsrefcnt) -nsRDFToolbarDataModelItem::AddRef(void) -{ - return nsRDFDataModelItem::AddRef(); -} - - -NS_IMETHODIMP_(nsrefcnt) -nsRDFToolbarDataModelItem::Release(void) -{ - return nsRDFDataModelItem::Release(); -} - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::QueryInterface(const nsIID& iid, void** result) -{ - if (NULL == result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kIToolbarDMItemIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - - // delegate to the superclass. - return nsRDFDataModelItem::QueryInterface(iid, result); -} - - -//////////////////////////////////////////////////////////////////////// -// nsIDMItem interface -- delgates to superclass - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetIconImage(nsIImage*& image, nsIImageGroup* group) const -{ - return nsRDFDataModelItem::GetIconImage(image, group); -} - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetOpenState(PRBool& result) const -{ - return nsRDFDataModelItem::GetOpenState(result); -} - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetChildCount(PRUint32& count) const -{ - return nsRDFDataModelItem::GetChildCount(count); -} - - - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetNthChild(nsIDMItem*& pItem, PRUint32 item) const -{ - return nsRDFDataModelItem::GetNthChild(pItem, item); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetSubtreeSize(PRUint32& result) const -{ - return nsRDFDataModelItem::GetSubtreeSize(result); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetParent(nsIDMItem*& pItem) const -{ - return nsRDFDataModelItem::GetParent(pItem); -} - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::SetOpenState(PRBool open) -{ - return nsRDFDataModelItem::SetOpenState(open); -} - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetStringPropertyValue(nsString& result, const nsString& property) const -{ - return nsRDFDataModelItem::GetStringPropertyValue(result, property); -} - - -NS_IMETHODIMP -nsRDFToolbarDataModelItem::GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const -{ - return nsRDFDataModelItem::GetIntPropertyValue(value, itemProperty); -} - -//////////////////////////////////////////////////////////////////////// -// nsIToolbarDMItem interface diff --git a/rdf/src/nsRDFToolbarDataModelItem.h b/rdf/src/nsRDFToolbarDataModelItem.h deleted file mode 100644 index 2595b76d79b2..000000000000 --- a/rdf/src/nsRDFToolbarDataModelItem.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- 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. - */ - -#ifndef nsRDFTreeDataModelItem_h__ -#define nsRDFTreeDataModelItem_h__ - -#include "rdf.h" -#include "nsRDFDataModelItem.h" -#include "nsIToolbarDMItem.h" - -class nsRDFToolbarDataModel; - -//////////////////////////////////////////////////////////////////////// - -class nsRDFToolbarDataModelItem : public nsIToolbarDMItem, public nsRDFDataModelItem -{ -public: - nsRDFToolbarDataModelItem(nsRDFToolbarDataModel& Toolbar, RDF_Resource resource); - virtual ~nsRDFToolbarDataModelItem(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface -- delegates to superclass - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - NS_IMETHOD QueryInterface(const nsIID& iid, void** result); - - - //////////////////////////////////////////////////////////////////////// - // nsIDMItem interface -- delegates to superclass - - // Inspectors - NS_IMETHOD GetIconImage(nsIImage*& pImage, nsIImageGroup* pGroup) const; - NS_IMETHOD GetOpenState(PRBool& answer) const; - - // Methods for iterating over children. - NS_IMETHOD GetChildCount(PRUint32& count) const; - NS_IMETHOD GetNthChild(nsIDMItem*& pItem, PRUint32 item) const; - NS_IMETHOD GetSubtreeSize(PRUint32& result) const; - - // Parent access - NS_IMETHOD GetParent(nsIDMItem*& pItem) const; - - // Setters - NS_IMETHOD SetOpenState(PRBool open); - - // Methods to query the data model for a specific item displayed within the widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& itemProperty) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const; - - - //////////////////////////////////////////////////////////////////////// - // nsIToolbarItem interface - - -private: -}; - -//////////////////////////////////////////////////////////////////////// - - -#endif // nsRDFToolbarDataModelItem_h__ diff --git a/rdf/src/nsRDFTreeColumn.cpp b/rdf/src/nsRDFTreeColumn.cpp deleted file mode 100644 index 5772392042fc..000000000000 --- a/rdf/src/nsRDFTreeColumn.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* -*- 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 "nsRDFTreeColumn.h" -#include "nsRDFTreeDataModel.h" -#include "nsIDMWidget.h" -#include "nsIDataModel.h" - -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); -static NS_DEFINE_IID(kITreeColumnIID, NS_ITREECOLUMN_IID); -static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); - -const PRUint32 nsRDFTreeColumn::kDefaultWidth = 64; // XXX - -//////////////////////////////////////////////////////////////////////// - -nsRDFTreeColumn::nsRDFTreeColumn(nsRDFTreeDataModel& tree, - const nsString& name, - RDF_Resource property, - PRUint32 width) - : mTree(tree), - mName(name), - mProperty(property), - mWidth(width), - mSortState(eColumnSortState_Unsorted), - mDesiredPercentage(0.0) -{ - NS_INIT_REFCNT(); - mTree.AddRef(); -} - - -nsRDFTreeColumn::~nsRDFTreeColumn(void) -{ -} - - -NS_IMPL_ADDREF(nsRDFTreeColumn); -NS_IMPL_RELEASE(nsRDFTreeColumn); - -NS_IMETHODIMP -nsRDFTreeColumn::QueryInterface(const nsIID& iid, void** result) -{ - if (! result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kITreeColumnIID) || - iid.Equals(kISupportsIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - else if (iid.Equals(kIRDFResourceIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - return NS_ERROR_NO_INTERFACE; -} - - -//////////////////////////////////////////////////////////////////////// - -NS_IMETHODIMP -nsRDFTreeColumn::GetPixelWidth(PRUint32& width) const -{ - width = mWidth; - return NS_OK; -} - - - -NS_IMETHODIMP -nsRDFTreeColumn::GetDesiredPercentage(double& percentage) const -{ - percentage = mDesiredPercentage; - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeColumn::GetSortState(nsColumnSortState& answer) const -{ - answer = mSortState; - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeColumn::GetColumnName(nsString& name) const -{ - name = mName; - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeColumn::SetPixelWidth(PRUint32 newWidth) -{ - mWidth = newWidth; - return NS_OK; -} - - -//////////////////////////////////////////////////////////////////////// -// nsIRDFResource interface - -NS_IMETHODIMP -nsRDFTreeColumn::GetResource(RDF_Resource& result) const -{ - result = mProperty; - return NS_OK; -} - - -//////////////////////////////////////////////////////////////////////// -// Implementation methods - -void -nsRDFTreeColumn::SetVisibility(PRBool visible) -{ - if (visible != mVisible) { - mVisible = visible; - - nsIDataModel* model; - if (NS_SUCCEEDED(mTree.QueryInterface(kIDataModelIID, (void**) &model))) { - nsIDMWidget* dmWidget; - - // XXX if interface inheirits... - //if (NS_SUCCEEDED(mTree.GetDMWidget(dmWidget))) { - - if (NS_SUCCEEDED(model->GetDMWidget(dmWidget))) { -#if 0 - // XXX IMO, this should be in its own interface. Need to ask Hyatt... - nsITreeWidget* treeWidget; - if (NS_SUCCEEDED(dmWidget->QueryInterface(kITreeWidgetIID, &treeWidget))) { - treeWidget->OnColumnVisibilityChanged(static_cast(this), - mVisible); - - treeWidget->Release(); - } -#endif - dmWidget->Release(); - } - model->Release(); - } - } -} - - -PRBool -nsRDFTreeColumn::IsVisible(void) const -{ - return mVisible; -} - diff --git a/rdf/src/nsRDFTreeColumn.h b/rdf/src/nsRDFTreeColumn.h deleted file mode 100644 index 0748e1d86f9b..000000000000 --- a/rdf/src/nsRDFTreeColumn.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- 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. - */ - -#ifndef nsRDFTreeColumn_h__ -#define nsRDFTreeColumn_h__ - -#include "nsString.h" -#include "nsITreeColumn.h" -#include "nsIRDFResource.h" -#include "rdf.h" - -class nsRDFTreeDataModel; - -class nsRDFTreeColumn : public nsITreeColumn, public nsIRDFResource { -private: - nsRDFTreeDataModel& mTree; - nsString mName; - RDF_Resource mProperty; - PRUint32 mWidth; - nsColumnSortState mSortState; - double mDesiredPercentage; - PRBool mVisible; - - static const PRUint32 kDefaultWidth; - -public: - nsRDFTreeColumn(nsRDFTreeDataModel& tree, - const nsString& name, - const RDF_Resource property, - PRUint32 width = kDefaultWidth); - - virtual ~nsRDFTreeColumn(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface - - NS_DECL_ISUPPORTS - - //////////////////////////////////////////////////////////////////////// - // nsITreeColumn interface - - // Inspectors - NS_IMETHOD GetPixelWidth(PRUint32& width) const; - NS_IMETHOD GetDesiredPercentage(double& percentage) const; - NS_IMETHOD GetSortState(nsColumnSortState& answer) const; - NS_IMETHOD GetColumnName(nsString& name) const; - - // Setters - NS_IMETHOD SetPixelWidth(PRUint32 newWidth); - - //////////////////////////////////////////////////////////////////////// - // nsIRDFResource interface - - NS_IMETHOD GetResource(RDF_Resource& result /* out */) const; - - //////////////////////////////////////////////////////////////////////// - // Implementation methods - - void SetVisibility(PRBool visible); - - PRBool IsVisible(void) const; -}; - -#endif // nsRDFTreeColumn_h__ diff --git a/rdf/src/nsRDFTreeDataModel.cpp b/rdf/src/nsRDFTreeDataModel.cpp deleted file mode 100644 index 75ae7aaf01fc..000000000000 --- a/rdf/src/nsRDFTreeDataModel.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/* -*- 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 "nsRDFTreeDataModel.h" -#include "nsRDFTreeColumn.h" -#include "nsRDFTreeDataModelItem.h" -#include "rdf-int.h" - -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kIDataModelIID, NS_IDATAMODEL_IID); -static NS_DEFINE_IID(kITreeDataModelIID, NS_ITREEDATAMODEL_IID); -static NS_DEFINE_IID(kIRDFResourceIID, NS_IRDFRESOURCE_IID); - - -//////////////////////////////////////////////////////////////////////// - -#ifdef ALLOW_DYNAMIC_CAST -#define DYNAMIC_CAST(__type, __pointer) dynamic_cast<__type>(__pointer) -#else -#define DYNAMIC_CAST(__type, __pointer) ((__type)(__pointer)) -#endif - -static nsITreeDMItem* -rdf_GetNth(nsIDMItem* node, PRUint32 n) -{ - // XXX this algorithm sucks: it's O(m*log(n)), where m is the - // branching factor and n is the depth of the tree. We need to - // eventually do something like the old HT did: keep a - // vector. Alternatively, hyatt suggested that is we can keep a - // pointer to the topmost node, m will be kept small. - - if (n == 0) { - node->AddRef(); - return DYNAMIC_CAST(nsITreeDMItem*, node); - } - - // iterate through all of the children. since we know the subtree - // height of each child, we can determine a range of indices - // contained within the subtree. - PRUint32 childCount; - if (NS_SUCCEEDED(node->GetChildCount(childCount))) { - PRUint32 firstIndexInSubtree = 1; - for (PRUint32 i = 0; i < childCount; ++i) { - nsIDMItem* child; - if (NS_FAILED(node->GetNthChild(child, i))) { - PR_ASSERT(0); - continue; - } - - PRUint32 subtreeSize; - child->GetSubtreeSize(subtreeSize); - - PRUint32 lastIndexInSubtree = firstIndexInSubtree + subtreeSize; - - nsITreeDMItem* result = NULL; - if (n >= firstIndexInSubtree && n < lastIndexInSubtree) - result = rdf_GetNth(child, n - firstIndexInSubtree); - - child->Release(); - if (result) - return result; - - firstIndexInSubtree = lastIndexInSubtree; - } - } - - // n was larger than the total number of elements in the tree! You - // should've called GetTreeItemCount() first... - PR_ASSERT(0); - return NULL; -} - - - -//////////////////////////////////////////////////////////////////////// - -nsRDFTreeDataModel::nsRDFTreeDataModel(void) -{ -} - - - -nsRDFTreeDataModel::~nsRDFTreeDataModel(void) -{ - for (PRUint32 i = 0; i < mColumns.GetSize(); ++i) { - nsRDFTreeColumn* column = static_cast(mColumns[i]); - - PR_ASSERT(column); - if (! column) - continue; - - column->Release(); - } -} - -NS_IMETHODIMP_(nsrefcnt) -nsRDFTreeDataModel::AddRef(void) -{ - return nsRDFDataModel::AddRef(); // delegate to the superclass -} - -NS_IMETHODIMP_(nsrefcnt) -nsRDFTreeDataModel::Release(void) -{ - return nsRDFDataModel::Release(); // delegate to the superclass -} - -NS_IMETHODIMP -nsRDFTreeDataModel::QueryInterface(const nsIID& iid, void** result) -{ - if (NULL == result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kITreeDataModelIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - return nsRDFDataModel::QueryInterface(iid, result); -} - -//////////////////////////////////////////////////////////////////////// -// nsIDataModel implementation -- delgates to superclass - -NS_IMETHODIMP -nsRDFTreeDataModel::InitFromURL(const nsString& url) -{ - nsresult res = nsRDFDataModel::InitFromURL(url); - if (NS_SUCCEEDED(res)) - res = CreateColumns(); - - return res; -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::InitFromResource(nsIDMItem* pResource) -{ - return nsRDFDataModel::InitFromResource(pResource); -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetDMWidget(nsIDMWidget*& widget) const -{ - return nsRDFDataModel::GetDMWidget(widget); -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::SetDMWidget(nsIDMWidget* widget) -{ - return nsRDFDataModel::SetDMWidget(widget); -} - - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetStringPropertyValue(nsString& value, const nsString& property) const -{ - return nsRDFDataModel::GetStringPropertyValue(value, property); -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetIntPropertyValue(PRInt32& value, const nsString& property) const -{ - return nsRDFDataModel::GetIntPropertyValue(value, property); -} - -//////////////////////////////////////////////////////////////////////// -// nsITreeDataModel interface - -NS_IMETHODIMP -nsRDFTreeDataModel::GetVisibleColumnCount(PRUint32& count) const -{ - count = 0; - for (PRUint32 i = 0; i < mColumns.GetSize(); ++i) { - nsRDFTreeColumn* column = static_cast(mColumns.Get(i)); - if (column->IsVisible()) - ++count; - } - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetColumnCount(PRUint32& count) const -{ - count = mColumns.GetSize(); - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetNthColumn(nsITreeColumn*& pColumn, PRUint32 n) const -{ - if (n < 0 || n > mColumns.GetUpperBound()) { - PR_ASSERT(0); - return NS_ERROR_ILLEGAL_VALUE; - } - - pColumn = static_cast(mColumns.Get(n)); - pColumn->AddRef(); - - return NS_OK; -} - - -NS_IMETHODIMP -nsRDFTreeDataModel::GetFirstVisibleItemIndex(PRUint32& index) const -{ - // XXX hack! where do we ever set this??? - index = 0; - return NS_OK; -} - -NS_IMETHODIMP -nsRDFTreeDataModel::GetTreeItemCount(PRUint32& result) const -{ - nsRDFDataModelItem* root = GetRoot(); - if (! root) - return NS_ERROR_NOT_INITIALIZED; - - return root->GetSubtreeSize(result); -} - -NS_IMETHODIMP -nsRDFTreeDataModel::GetNthTreeItem(nsITreeDMItem*& pItem, PRUint32 n) const -{ - nsRDFDataModelItem* root = GetRoot(); - if (! root) - return NS_ERROR_NOT_INITIALIZED; - - pItem = rdf_GetNth(root, n); - return pItem ? NS_OK : NS_ERROR_INVALID_ARG; -} - -NS_IMETHODIMP -nsRDFTreeDataModel::GetItemTextForColumn(nsString& result, - nsITreeDMItem* pItem, - nsITreeColumn* pColumn) const -{ - // XXX this is a horribly simplified version of what - // HT_GetNodeData() does. Hopefully it's enough to do the job for - // now. - - nsresult res = NS_OK; - nsIRDFResource* itemRsrc = NULL; - nsIRDFResource* columnRsrc = NULL; - - do { - if (NS_FAILED(res = pItem->QueryInterface(kIRDFResourceIID, (void**) &itemRsrc))) - break; - - if (NS_FAILED(res = pColumn->QueryInterface(kIRDFResourceIID, (void**) &columnRsrc))) - break; - - RDF_Resource item; - if (NS_FAILED(res = itemRsrc->GetResource(item))) - break; - - RDF_Resource property; - if (NS_FAILED(res = columnRsrc->GetResource(property))) - break; - - const char* text = - (const char*) RDF_GetSlotValue(GetDB(), - item, - property, // property - RDF_STRING_TYPE, - PR_FALSE, - PR_TRUE); - - if (! text) { - res = NS_ERROR_UNEXPECTED; - break; - } - - result = nsString(text); - } while (0); - - if (columnRsrc) - columnRsrc->Release(); - - if (itemRsrc) - itemRsrc->Release(); - - return NS_OK; -} - - -//////////////////////////////////////////////////////////////////////// -// nsRDFTreeDataModel implementation methods - -nsresult -nsRDFTreeDataModel::CreateColumns(void) -{ - /* - // XXX manually add columns for testing - AddColumn(nsString("Name"), gCoreVocab->RDF_name); - AddColumn(nsString("Last Modified"), gWebData->RDF_lastModifiedDate); - AddColumn(nsString("Last Visited"), gWebData->RDF_lastVisitDate); - AddColumn(nsString("Description"), gWebData->RDF_description); - return NS_OK; - */ - - // This mostly came over from HT_NewView() - nsRDFDataModelItem* root = GetRoot(); - PR_ASSERT(root); - if (! root) - return NS_ERROR_NULL_POINTER; // XXX need something better here - - RDF_Resource rootResource; - if (NS_FAILED(root->GetResource(rootResource))) - return NS_ERROR_UNEXPECTED; - - RDF_Cursor cursor; - cursor = RDF_GetSources(GetDB(), rootResource, - gNavCenter->RDF_Column, - RDF_RESOURCE_TYPE, PR_TRUE); - - PR_ASSERT(cursor != NULL); - if (cursor == NULL) - return NS_ERROR_UNEXPECTED; // XXX need something better here - - RDF_Resource r; - while ((r = static_cast(RDF_NextValue(cursor))) != NULL) { - if (resourceID(r) == NULL) - break; - -#if 0 // XXX no datatype support yet... - PRUint32 type; - type = (PRUint32) RDF_GetSlotValue(GetDB(), r, gNavCenter->RDF_ColumnDataType, - RDF_INT_TYPE, PR_FALSE, PR_TRUE); - - if (!type) - type = HT_COLUMN_STRING; -#endif - - PRUint32 width; - width = (PRUint32) RDF_GetSlotValue(GetDB(), r, gNavCenter->RDF_ColumnWidth, - RDF_INT_TYPE, PR_FALSE, PR_TRUE); - - const char* name; - name = (const char *) RDF_GetSlotValue(GetDB(), r, gCoreVocab->RDF_name, - RDF_STRING_TYPE, PR_FALSE, PR_TRUE); - - nsRDFTreeColumn* column = new nsRDFTreeColumn(*this, name, r, width); - - PR_ASSERT(column); - if (! column) - continue; - - column->AddRef(); - mColumns.Add(column); - } - RDF_DisposeCursor(cursor); - return NS_OK; -} - -void -nsRDFTreeDataModel::AddColumn(const nsString& name, RDF_Resource property) -{ - nsRDFTreeColumn* column = new nsRDFTreeColumn(*this, name, property); - mColumns.Add(column); -} - - -NS_METHOD -nsRDFTreeDataModel::CreateItem(RDF_Resource r, nsRDFDataModelItem*& result) -{ - result = new nsRDFTreeDataModelItem(*this, r); - if (! result) - return NS_ERROR_OUT_OF_MEMORY; - - result->AddRef(); // like a good little COM citizen - return NS_OK; -} diff --git a/rdf/src/nsRDFTreeDataModel.h b/rdf/src/nsRDFTreeDataModel.h deleted file mode 100644 index 0b91aecfe322..000000000000 --- a/rdf/src/nsRDFTreeDataModel.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; 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. - */ - -#ifndef nsRDFTreeDataModel_h__ -#define nsRDFTreeDataModel_h__ - -#include "nsRDFDataModel.h" -#include "nsITreeDataModel.h" -#include "nsVector.h" -#include "rdf.h" - -//////////////////////////////////////////////////////////////////////// - -/** - * An implementation for the tree widget model. - */ -class nsRDFTreeDataModel : public nsITreeDataModel, public nsRDFDataModel { -public: - nsRDFTreeDataModel(void); - virtual ~nsRDFTreeDataModel(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface -- delgates to superclass - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - NS_IMETHOD QueryInterface(const nsIID& iid, void** result); - - - //////////////////////////////////////////////////////////////////////// - // nsIDataModel interface -- delgates to superclass - - // Initializers - NS_IMETHOD InitFromURL(const nsString& url); - NS_IMETHOD InitFromResource(nsIDMItem* pResource); - - // Inspectors - NS_IMETHOD GetDMWidget(nsIDMWidget*& pWidget) const; - - // Setters - NS_IMETHOD SetDMWidget(nsIDMWidget* pWidget); - - // Methods to query the data model for property values for an entire widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& property) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& property) const; - - - //////////////////////////////////////////////////////////////////////// - // nsITreeDataModel interface - - // Column APIs - NS_IMETHOD GetVisibleColumnCount(PRUint32& count) const; - NS_IMETHOD GetColumnCount(PRUint32& count) const; - NS_IMETHOD GetNthColumn(nsITreeColumn*& pColumn, PRUint32 n) const; - - // TreeItem APIs - NS_IMETHOD GetFirstVisibleItemIndex(PRUint32& index) const; - NS_IMETHOD GetTreeItemCount(PRUint32& result) const; - NS_IMETHOD GetNthTreeItem(nsITreeDMItem*& pItem, PRUint32 n) const; - NS_IMETHOD GetItemTextForColumn(nsString& nodeText, nsITreeDMItem* pItem, nsITreeColumn* pColumn) const; - - //////////////////////////////////////////////////////////////////////// - // Implemantation methods - - void AddColumn(const nsString& name, RDF_Resource property); - - virtual NS_METHOD - CreateItem(RDF_Resource r, nsRDFDataModelItem*& result); - -private: - nsVector mColumns; - - nsresult CreateColumns(void); -}; - - - -#endif // nsRDFTreeDataModel_h__ diff --git a/rdf/src/nsRDFTreeDataModelItem.cpp b/rdf/src/nsRDFTreeDataModelItem.cpp deleted file mode 100644 index 6b51aeda63ce..000000000000 --- a/rdf/src/nsRDFTreeDataModelItem.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* -*- 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 "nsRDFTreeDataModelItem.h" -#include "nsRDFTreeDataModel.h" - -const PRUint32 nsRDFTreeDataModelItem::kInvalidIndentationLevel = PRUint32(-1); - -static NS_DEFINE_IID(kIDMItemIID, NS_IDMITEM_IID); -static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kITreeDMItemIID, NS_ITREEDMITEM_IID); - -//////////////////////////////////////////////////////////////////////// - -nsRDFTreeDataModelItem::nsRDFTreeDataModelItem(nsRDFTreeDataModel& tree, - RDF_Resource resource) - : nsRDFDataModelItem(tree, resource) -{ -} - - -nsRDFTreeDataModelItem::~nsRDFTreeDataModelItem(void) -{ -} - - -NS_IMETHODIMP_(nsrefcnt) -nsRDFTreeDataModelItem::AddRef(void) -{ - return nsRDFDataModelItem::AddRef(); -} - - -NS_IMETHODIMP_(nsrefcnt) -nsRDFTreeDataModelItem::Release(void) -{ - return nsRDFDataModelItem::Release(); -} - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::QueryInterface(const nsIID& iid, void** result) -{ - if (NULL == result) - return NS_ERROR_NULL_POINTER; - - *result = NULL; - if (iid.Equals(kITreeDMItemIID)) { - *result = static_cast(this); - AddRef(); - return NS_OK; - } - - // delegate to the superclass. - return nsRDFDataModelItem::QueryInterface(iid, result); -} - - -//////////////////////////////////////////////////////////////////////// -// nsIDMItem interface -- delgates to superclass - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetIconImage(nsIImage*& image, nsIImageGroup* group) const -{ - return nsRDFDataModelItem::GetIconImage(image, group); -} - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetOpenState(PRBool& result) const -{ - return nsRDFDataModelItem::GetOpenState(result); -} - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetChildCount(PRUint32& count) const -{ - return nsRDFDataModelItem::GetChildCount(count); -} - - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetNthChild(nsIDMItem*& pItem, PRUint32 item) const -{ - return nsRDFDataModelItem::GetNthChild(pItem, item); -} - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetSubtreeSize(PRUint32& result) const -{ - return nsRDFDataModelItem::GetSubtreeSize(result); -} - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetParent(nsIDMItem*& pItem) const -{ - return nsRDFDataModelItem::GetParent(pItem); -} - -NS_IMETHODIMP -nsRDFTreeDataModelItem::SetOpenState(PRBool open) -{ - return nsRDFDataModelItem::SetOpenState(open); -} - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetStringPropertyValue(nsString& result, const nsString& property) const -{ - return nsRDFDataModelItem::GetStringPropertyValue(result, property); -} - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const -{ - return nsRDFDataModelItem::GetIntPropertyValue(value, itemProperty); -} - - -//////////////////////////////////////////////////////////////////////// -// nsITreeDMItem interface - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetTriggerImage(nsIImage*& pImage, nsIImageGroup* pGroup) const -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - - -NS_IMETHODIMP -nsRDFTreeDataModelItem::GetIndentationLevel(PRUint32& indentation) const -{ - PRUint32 i = 0; - - nsRDFDataModelItem* item = - static_cast(const_cast(this)); - - while ((item = item->GetParent()) != NULL) - i += 1; // XXX should this be some pixel value? - - indentation = i; - return NS_OK; -} diff --git a/rdf/src/nsRDFTreeDataModelItem.h b/rdf/src/nsRDFTreeDataModelItem.h deleted file mode 100644 index de385daa6e38..000000000000 --- a/rdf/src/nsRDFTreeDataModelItem.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- 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. - */ - - -#ifndef nsRDFTreeDataModelItem_h__ -#define nsRDFTreeDataModelItem_h__ - -#include "rdf.h" -#include "nsRDFDataModelItem.h" -#include "nsITreeDMItem.h" - -class nsRDFTreeDataModel; - -//////////////////////////////////////////////////////////////////////// - -class nsRDFTreeDataModelItem : public nsITreeDMItem, public nsRDFDataModelItem -{ -public: - nsRDFTreeDataModelItem(nsRDFTreeDataModel& tree, RDF_Resource resource); - virtual ~nsRDFTreeDataModelItem(void); - - //////////////////////////////////////////////////////////////////////// - // nsISupports interface - - NS_IMETHOD_(nsrefcnt) AddRef(void); - NS_IMETHOD_(nsrefcnt) Release(void); - NS_IMETHOD QueryInterface(const nsIID& iid, void** result); - - //////////////////////////////////////////////////////////////////////// - // nsIDMItem interface -- delegate to the superclass - - // Inspectors - NS_IMETHOD GetIconImage(nsIImage*& pImage, nsIImageGroup* pGroup) const; - NS_IMETHOD GetOpenState(PRBool& answer) const; - - // Methods for iterating over children. - NS_IMETHOD GetChildCount(PRUint32& count) const; - NS_IMETHOD GetNthChild(nsIDMItem*& pItem, PRUint32 item) const; - NS_IMETHOD GetSubtreeSize(PRUint32& result) const; - - // Parent access - NS_IMETHOD GetParent(nsIDMItem*& pItem) const; - - // Setters - NS_IMETHOD SetOpenState(PRBool open); - - // Methods to query the data model for a specific item displayed within the widget. - NS_IMETHOD GetStringPropertyValue(nsString& value, const nsString& itemProperty) const; - NS_IMETHOD GetIntPropertyValue(PRInt32& value, const nsString& itemProperty) const; - - //////////////////////////////////////////////////////////////////////// - // nsITreeItem interface - - // Inspectors - NS_IMETHOD GetTriggerImage(nsIImage*& pImage, nsIImageGroup* pGroup) const; - NS_IMETHOD GetIndentationLevel(PRUint32& indentation) const; - - // Setters - - - -private: - mutable PRUint32 mCachedIndentationLevel; - - static const PRUint32 kInvalidIndentationLevel; -}; - -//////////////////////////////////////////////////////////////////////// - - -#endif // nsRDFTreeDataModelItem_h__ diff --git a/rdf/src/nsSimpleDataBase.cpp b/rdf/src/nsSimpleDataBase.cpp new file mode 100644 index 000000000000..90b186f380bf --- /dev/null +++ b/rdf/src/nsSimpleDataBase.cpp @@ -0,0 +1,638 @@ +/* -*- 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 "nsSimpleDataBase.h" +#include "nsIRDFCursor.h" +#include "nsIRDFNode.h" +#include "nsISupportsArray.h" +#include "nsRDFCID.h" +#include "nsRepository.h" +#include "prlog.h" + +/* + + A simple "database" implementation. An RDF database is just a + "strategy" pattern for combining individual data sources into a + collective graph. + + This implementation is pretty much lifted straight out of the old C + RDF implementation. As such, it inheirits some horrible problems. + + 1) A database is a hard-coded collection of data sources. What you'd + really like would be fore data sources to be discovered at + runtime, and added in to the database as needed. + + 2) The aggregation mechanism is horribly ad hoc, specifically, with + respect to negative assertions. It works something like this. + Check the "first" data source for a negative assertion. If it has + one, then return it. Otherwise, check the "rest" of the data + sources for a positive assertion. + + 3) Related to the above, there are no clear semantics for ordering + or precedence. Things all depend on the order that you said "add + this data source". + +*/ + +static NS_DEFINE_IID(kIRDFCursorIID, NS_IRDFCURSOR_IID); +static NS_DEFINE_IID(kIRDFDataBaseIID, NS_IRDFDATABASE_IID); +static NS_DEFINE_IID(kIRDFDataSourceIID, NS_IRDFDATASOURCE_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static NS_DEFINE_CID(kRDFBookmarkDataSourceCID, NS_RDFBOOKMARKDATASOURCE_CID); + +//////////////////////////////////////////////////////////////////////// +// MultiCursor + +class MultiCursor : public nsIRDFCursor { +private: + nsIRDFDataSource* mDataSource0; + nsIRDFDataSource** mDataSources; + nsIRDFCursor* mCurrentCursor; + nsIRDFNode* mNextResult; + PRBool mNextTruthValue; + PRInt32 mNextDataSource; + PRInt32 mCount; + +public: + MultiCursor(nsVoidArray& dataSources); + virtual ~MultiCursor(void); + + NS_DECL_ISUPPORTS; + + NS_IMETHOD HasMoreElements(PRBool& result); + NS_IMETHOD GetNext(nsIRDFNode*& next, PRBool& tv); + + virtual nsresult + GetCursor(nsIRDFDataSource* ds, nsIRDFCursor*& result) = 0; + + virtual nsresult + HasNegation(nsIRDFDataSource* ds0, + nsIRDFNode* nodeToTest, + PRBool tv, + PRBool& result) = 0; +}; + + +MultiCursor::MultiCursor(nsVoidArray& dataSources) + : mDataSource0(NULL), + mDataSources(NULL), + mCurrentCursor(NULL), + mNextResult(NULL), + mCount(0), + mNextDataSource(0) +{ + NS_INIT_REFCNT(); + + mCount = dataSources.Count(); + mDataSources = new nsIRDFDataSource*[mCount]; + + PR_ASSERT(mDataSources); + if (! mDataSources) + return; + + for (PRInt32 i = 0; i < mCount; ++i) { + mDataSources[i] = static_cast(dataSources[i]); + NS_ADDREF(mDataSources[i]); + } + + mDataSource0 = mDataSources[0]; + NS_ADDREF(mDataSource0); +} + + +MultiCursor::~MultiCursor(void) +{ + NS_IF_RELEASE(mNextResult); + NS_IF_RELEASE(mCurrentCursor); + for (PRInt32 i = mCount - 1; i >= 0; --i) { + NS_IF_RELEASE(mDataSources[i]); + } + NS_IF_RELEASE(mDataSource0); +} + +NS_IMPL_ISUPPORTS(MultiCursor, kIRDFCursorIID); + +NS_IMETHODIMP +MultiCursor::HasMoreElements(PRBool& result) +{ + nsresult rv; + if (! mDataSources) + return NS_ERROR_OUT_OF_MEMORY; + + // If we've already queued up a next target, then yep, there are + // more elements. + if (mNextResult) { + result = PR_TRUE; + return NS_OK; + } + + // Otherwise, we'll need to find a next target, switching cursors + // if necessary. + result = PR_FALSE; + + while (mNextDataSource < mCount) { + if (! mCurrentCursor) { + // We don't have a current cursor, so create a new one on + // the next data source. + rv = GetCursor(mDataSources[mNextDataSource], mCurrentCursor); + + if (NS_FAILED(rv)) + return rv; + } + + do { + if (NS_FAILED(rv = mCurrentCursor->HasMoreElements(result))) + return rv; + + // Is the current cursor depleted? + if (!result) + break; + + // Even if the current cursor has more elements, we still + // need to check that the current element isn't masked by + // the "main" data source. + + // "Peek" ahead and pull out the next target. + if (NS_FAILED(mCurrentCursor->GetNext(mNextResult, mNextTruthValue))) + return rv; + + // See if data source zero has the negation + PRBool hasNegation; + if (NS_FAILED(rv = HasNegation(mDataSource0, + mNextResult, + mNextTruthValue, + hasNegation))) + return rv; + + // if not, we're done + if (! hasNegation) + return NS_OK; + + // Otherwise, we found the negation in data source + // zero. Gotta keep lookin'... + NS_RELEASE(mNextResult); + } while (1); + + NS_RELEASE(mCurrentCursor); + NS_RELEASE(mDataSources[mNextDataSource]); + ++mNextDataSource; + } + + // if we get here, there aren't any elements left. + return NS_OK; +} + + +NS_IMETHODIMP +MultiCursor::GetNext(nsIRDFNode*& next, PRBool& tv) +{ + nsresult rv; + PRBool hasMore; + if (NS_FAILED(rv = HasMoreElements(hasMore))) + return rv; + + if (! hasMore) + return NS_ERROR_UNEXPECTED; + + next = mNextResult; // no need to AddRef() again... + tv = mNextTruthValue; + + mNextResult = NULL; // ...because we'll just "transfer ownership". + return NS_OK; +} + + +//////////////////////////////////////////////////////////////////////// +// dbNodeCursorImpl + +class dbNodeCursorImpl : public MultiCursor { +private: + nsIRDFNode* mSource; + nsIRDFNode* mProperty; + PRBool mTruthValue; + +public: + dbNodeCursorImpl(nsVoidArray& dataSources, + nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv); + + virtual ~dbNodeCursorImpl(); + + virtual nsresult + GetCursor(nsIRDFDataSource* ds, nsIRDFCursor*& result); + + virtual nsresult + HasNegation(nsIRDFDataSource* ds0, + nsIRDFNode* nodeToTest, + PRBool tv, + PRBool& result); +}; + +dbNodeCursorImpl::dbNodeCursorImpl(nsVoidArray& dataSources, + nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv) + : MultiCursor(dataSources), + mSource(source), + mProperty(property), + mTruthValue(tv) +{ + NS_IF_ADDREF(mSource); + NS_IF_ADDREF(mProperty); +} + + +dbNodeCursorImpl::~dbNodeCursorImpl(void) +{ + NS_IF_RELEASE(mProperty); + NS_IF_RELEASE(mSource); +} + +nsresult +dbNodeCursorImpl::GetCursor(nsIRDFDataSource* ds, nsIRDFCursor*& result) +{ + return ds->GetTargets(mSource, mProperty, mTruthValue, result); +} + +nsresult +dbNodeCursorImpl::HasNegation(nsIRDFDataSource* ds0, + nsIRDFNode* target, + PRBool tv, + PRBool& result) +{ + return ds0->HasAssertion(mSource, mProperty, target, !tv, result); +} + +//////////////////////////////////////////////////////////////////////// +// dbArcCursorImpl + +class dbArcCursorImpl : public MultiCursor { +private: + nsIRDFNode* mSource; + +public: + dbArcCursorImpl(nsVoidArray& dataSources, nsIRDFNode* source); + + virtual ~dbArcCursorImpl(); + + virtual nsresult + GetCursor(nsIRDFDataSource* ds, nsIRDFCursor*& result); + + virtual nsresult + HasNegation(nsIRDFDataSource* ds0, + nsIRDFNode* nodeToTest, + PRBool tv, + PRBool& result); +}; + +dbArcCursorImpl::dbArcCursorImpl(nsVoidArray& dataSources, + nsIRDFNode* source) + : MultiCursor(dataSources), + mSource(source) +{ + NS_IF_ADDREF(mSource); +} + + +dbArcCursorImpl::~dbArcCursorImpl(void) +{ + NS_IF_RELEASE(mSource); +} + +nsresult +dbArcCursorImpl::GetCursor(nsIRDFDataSource* ds, nsIRDFCursor*& result) +{ + return ds->ArcLabelsOut(mSource, result); +} + +nsresult +dbArcCursorImpl::HasNegation(nsIRDFDataSource* ds0, + nsIRDFNode* target, + PRBool tv, + PRBool& result) +{ + result = PR_FALSE; + return NS_OK; +} + + + +//////////////////////////////////////////////////////////////////////// +// nsSimpleDataBase + +nsSimpleDataBase::nsSimpleDataBase(void) +{ + NS_INIT_REFCNT(); + + // Add standard data sources here. + // XXX this is so wrong. + nsIRDFDataSource* ds; + if (NS_SUCCEEDED(nsRepository::CreateInstance(kRDFBookmarkDataSourceCID, + NULL, + kIRDFDataSourceIID, + (void**) &ds))) { + AddDataSource(ds); + NS_RELEASE(ds); + } +} + + +nsSimpleDataBase::~nsSimpleDataBase(void) +{ + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + NS_IF_RELEASE(ds); + } +} + +//////////////////////////////////////////////////////////////////////// +// nsISupports interface + +NS_IMPL_ADDREF(nsSimpleDataBase); +NS_IMPL_RELEASE(nsSimpleDataBase); + +NS_IMETHODIMP +nsSimpleDataBase::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = NULL; + if (iid.Equals(kIRDFDataBaseIID) || + iid.Equals(kIRDFDataSourceIID) || + iid.Equals(kISupportsIID)) { + *result = static_cast(this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + + +//////////////////////////////////////////////////////////////////////// +// nsIRDFDataSource interface + +NS_IMETHODIMP +nsSimpleDataBase::Initialize(const nsString& uri) +{ + PR_ASSERT(0); + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +nsSimpleDataBase::GetSource(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFNode*& source) +{ + PRInt32 count = mDataSources.Count(); + for (PRInt32 i = 0; i < count; ++i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + + if (NS_FAILED(ds->GetSource(property, target, tv, source))) + continue; + + // okay, found it. make sure we don't have the opposite + // asserted in the "main" data source + nsIRDFDataSource* ds0 = static_cast(mDataSources[0]); + nsIRDFNode* tmp; + if (NS_FAILED(ds->GetSource(property, target, !tv, tmp))) + return NS_OK; + + NS_RELEASE(tmp); + NS_RELEASE(source); + return NS_ERROR_FAILURE; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleDataBase::GetSources(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFCursor*& sources) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsSimpleDataBase::GetTarget(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFNode*& target) +{ + PRInt32 count = mDataSources.Count(); + for (PRInt32 i = 0; i < count; ++i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + + if (NS_FAILED(ds->GetTarget(source, property, tv, target))) + continue; + + // okay, found it. make sure we don't have the opposite + // asserted in the "main" data source + nsIRDFDataSource* ds0 = static_cast(mDataSources[0]); + nsIRDFNode* tmp; + if (NS_FAILED(ds0->GetTarget(source, property, !tv, tmp))) + return NS_OK; + + NS_RELEASE(tmp); + NS_RELEASE(target); + return NS_ERROR_FAILURE; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleDataBase::GetTargets(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFCursor*& targets) +{ + targets = new dbNodeCursorImpl(mDataSources, source, property, tv); + if (! targets) + return NS_ERROR_OUT_OF_MEMORY; + + NS_ADDREF(targets); + return NS_OK; +} + +NS_IMETHODIMP +nsSimpleDataBase::Assert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv) +{ + nsresult rv; + + // First see if we just need to remove a negative assertion from ds0. (Sigh) + nsIRDFDataSource* ds0 = static_cast(mDataSources[0]); + + PRBool ds0HasNegation; + if (NS_FAILED(rv = ds0->HasAssertion(source, property, target, !tv, ds0HasNegation))) + return rv; + + if (ds0HasNegation) { + if (NS_FAILED(rv = ds0->Unassert(source, property, target))) + return rv; + } + + // Now, see if the assertion has been "unmasked" + PRBool isAlreadyAsserted; + if (NS_FAILED(rv = HasAssertion(source, property, target, tv, isAlreadyAsserted))) + return rv; + + if (isAlreadyAsserted) + return NS_OK; + + // If not, iterate from the "remote-est" data source to the + // "local-est", trying to make the assertion. + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + if (NS_SUCCEEDED(ds->Assert(source, property, target, tv))) + return NS_OK; + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsSimpleDataBase::Unassert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target) +{ + // XXX I have no idea what this is trying to do. I'm just going to + // copy Guha's logic and punt. + nsresult rv; + PRInt32 count = mDataSources.Count(); + + for (PRInt32 i = 0; i < count; ++i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + if (NS_FAILED(rv = ds->Unassert(source, property, target))) + break; + } + + if (NS_FAILED(rv)) { + nsIRDFDataSource* ds0 = static_cast(mDataSources[0]); + rv = ds0->Assert(source, property, target); + } + return rv; +} + +NS_IMETHODIMP +nsSimpleDataBase::HasAssertion(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + PRBool& hasAssertion) +{ + nsresult rv; + + // First check to see if ds0 has the negation... + nsIRDFDataSource* ds0 = static_cast(mDataSources[0]); + + PRBool ds0HasNegation; + if (NS_FAILED(rv = ds0->HasAssertion(source, property, target, !tv, ds0HasNegation))) + return rv; + + if (ds0HasNegation) { + hasAssertion = PR_FALSE; + return NS_OK; + } + + // Otherwise, look through all the data sources to see if anyone + // has the positive... + PRInt32 count = mDataSources.Count(); + for (PRInt32 i = 0; i < count; ++i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + if (NS_FAILED(rv = ds->HasAssertion(source, property, target, tv, hasAssertion))) + return rv; + + if (hasAssertion) + return NS_OK; + } + + // If we get here, nobody had the assertion at all + return NS_OK; +} + +NS_IMETHODIMP +nsSimpleDataBase::AddObserver(nsIRDFObserver* n) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsSimpleDataBase::RemoveObserver(nsIRDFObserver* n) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsSimpleDataBase::ArcLabelsIn(nsIRDFNode* node, + nsIRDFCursor*& labels) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsSimpleDataBase::ArcLabelsOut(nsIRDFNode* source, + nsIRDFCursor*& labels) +{ + labels = new dbArcCursorImpl(mDataSources, source); + if (! labels) + return NS_ERROR_NULL_POINTER; + + NS_ADDREF(labels); + return NS_OK; +} + +NS_IMETHODIMP +nsSimpleDataBase::Flush() +{ + for (PRInt32 i = mDataSources.Count() - 1; i >= 0; --i) { + nsIRDFDataSource* ds = static_cast(mDataSources[i]); + ds->Flush(); + } + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// nsIRDFDataBase methods + +NS_IMETHODIMP +nsSimpleDataBase::AddDataSource(nsIRDFDataSource* source) +{ + if (! source) + return NS_ERROR_NULL_POINTER; + + mDataSources.InsertElementAt(source, 0); + NS_ADDREF(source); + return NS_OK; +} + + + diff --git a/rdf/src/nsSimpleDataBase.h b/rdf/src/nsSimpleDataBase.h new file mode 100644 index 000000000000..626121c86d10 --- /dev/null +++ b/rdf/src/nsSimpleDataBase.h @@ -0,0 +1,92 @@ +/* -*- 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. + */ + +#ifndef nsSimpleDataBase_h__ +#define nsSimpleDataBase_h__ + +#include "nsIRDFDataBase.h" +#include "nsVoidArray.h" + +class nsSimpleDataBase : public nsIRDFDataBase { +protected: + nsVoidArray mDataSources; + virtual ~nsSimpleDataBase(void); + +public: + nsSimpleDataBase(void); + + // nsISupports interface + NS_DECL_ISUPPORTS + + // nsIRDFDataSource interface + NS_IMETHOD Initialize(const nsString& uri); + + NS_IMETHOD GetSource(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFNode*& source); + + NS_IMETHOD GetSources(nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFCursor*& sources); + + NS_IMETHOD GetTarget(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFNode*& target); + + NS_IMETHOD GetTargets(nsIRDFNode* source, + nsIRDFNode* property, + PRBool tv, + nsIRDFCursor*& targets); + + NS_IMETHOD Assert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv = PR_TRUE); + + NS_IMETHOD Unassert(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target); + + NS_IMETHOD HasAssertion(nsIRDFNode* source, + nsIRDFNode* property, + nsIRDFNode* target, + PRBool tv, + PRBool& hasAssertion); + + NS_IMETHOD AddObserver(nsIRDFObserver* n); + + NS_IMETHOD RemoveObserver(nsIRDFObserver* n); + + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, + nsIRDFCursor*& labels); + + NS_IMETHOD ArcLabelsOut(nsIRDFNode* source, + nsIRDFCursor*& labels); + + NS_IMETHOD Flush(); + + // nsIRDFDataBase interface + NS_IMETHOD AddDataSource(nsIRDFDataSource* source); +}; + + +#endif // nsSimpleDataBase_h__ +