From 1f3422ad3a9eda3aa06949c83aeb298c4fb31cdd Mon Sep 17 00:00:00 2001 From: "chuang%netscape.com" Date: Mon, 17 May 1999 20:16:22 +0000 Subject: [PATCH] First check in. Address Book Data Source w/ hardcoded data. --- mailnews/addrbook/Makefile.in | 30 + mailnews/addrbook/build/Makefile.in | 79 ++ mailnews/addrbook/build/makefile.win | 68 ++ mailnews/addrbook/build/nsAbBaseCID.h | 50 ++ mailnews/addrbook/build/nsAbFactory.cpp | 285 +++++++ mailnews/addrbook/makefile.win | 22 + mailnews/addrbook/public/Makefile.in | 43 + mailnews/addrbook/public/makefile.win | 39 + mailnews/addrbook/public/nsIAbBase.h | 65 ++ mailnews/addrbook/public/nsIAbBase.idl | 41 + mailnews/addrbook/public/nsIAbCard.h | 64 ++ mailnews/addrbook/public/nsIAbCard.idl | 31 + mailnews/addrbook/public/nsIAbDirectory.h | 43 + mailnews/addrbook/public/nsIAbDirectory.idl | 28 + mailnews/addrbook/public/nsIAbListener.h | 45 ++ mailnews/addrbook/public/nsIAbListener.idl | 32 + mailnews/addrbook/src/Makefile.in | 43 + mailnews/addrbook/src/makefile.win | 79 ++ mailnews/addrbook/src/nsAbCard.cpp | 550 +++++++++++++ mailnews/addrbook/src/nsAbCard.h | 131 +++ mailnews/addrbook/src/nsAbDirectory.cpp | 493 ++++++++++++ mailnews/addrbook/src/nsAbDirectory.h | 119 +++ mailnews/addrbook/src/nsCardDataSource.cpp | 707 ++++++++++++++++ mailnews/addrbook/src/nsCardDataSource.h | 157 ++++ .../addrbook/src/nsDirectoryDataSource.cpp | 753 ++++++++++++++++++ mailnews/addrbook/src/nsDirectoryDataSource.h | 164 ++++ 26 files changed, 4161 insertions(+) create mode 100644 mailnews/addrbook/Makefile.in create mode 100644 mailnews/addrbook/build/Makefile.in create mode 100644 mailnews/addrbook/build/makefile.win create mode 100644 mailnews/addrbook/build/nsAbBaseCID.h create mode 100644 mailnews/addrbook/build/nsAbFactory.cpp create mode 100644 mailnews/addrbook/makefile.win create mode 100644 mailnews/addrbook/public/Makefile.in create mode 100644 mailnews/addrbook/public/makefile.win create mode 100644 mailnews/addrbook/public/nsIAbBase.h create mode 100644 mailnews/addrbook/public/nsIAbBase.idl create mode 100644 mailnews/addrbook/public/nsIAbCard.h create mode 100644 mailnews/addrbook/public/nsIAbCard.idl create mode 100644 mailnews/addrbook/public/nsIAbDirectory.h create mode 100644 mailnews/addrbook/public/nsIAbDirectory.idl create mode 100644 mailnews/addrbook/public/nsIAbListener.h create mode 100644 mailnews/addrbook/public/nsIAbListener.idl create mode 100644 mailnews/addrbook/src/Makefile.in create mode 100644 mailnews/addrbook/src/makefile.win create mode 100644 mailnews/addrbook/src/nsAbCard.cpp create mode 100644 mailnews/addrbook/src/nsAbCard.h create mode 100644 mailnews/addrbook/src/nsAbDirectory.cpp create mode 100644 mailnews/addrbook/src/nsAbDirectory.h create mode 100644 mailnews/addrbook/src/nsCardDataSource.cpp create mode 100644 mailnews/addrbook/src/nsCardDataSource.h create mode 100644 mailnews/addrbook/src/nsDirectoryDataSource.cpp create mode 100644 mailnews/addrbook/src/nsDirectoryDataSource.h diff --git a/mailnews/addrbook/Makefile.in b/mailnews/addrbook/Makefile.in new file mode 100644 index 000000000000..4656f221247a --- /dev/null +++ b/mailnews/addrbook/Makefile.in @@ -0,0 +1,30 @@ +#!gmake +# +# 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. + +DEPTH = ../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +DIRS = public src build + +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + diff --git a/mailnews/addrbook/build/Makefile.in b/mailnews/addrbook/build/Makefile.in new file mode 100644 index 000000000000..172e9c4c091f --- /dev/null +++ b/mailnews/addrbook/build/Makefile.in @@ -0,0 +1,79 @@ +#!gmake +# +# 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. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE=mailnews +LIBRARY_NAME=addrbook +IS_COMPONENT=1 +CPPSRCS= \ + nsAbFactory.cpp \ + $(NULL) + +EXPORTS = \ + nsAbBaseCID.h \ + $(NULL) + +SHARED_LIBRARY_LIBS = \ + $(NULL) + +EXTRA_DSO_LDOPTS = \ + $(MKSHLIB_FORCE_ALL) \ + $(SHARED_LIBRARY_LIBS) \ + $(MKSHLIB_UNFORCE_ALL) \ + -lmozjs \ + -ljsdom \ + -ljsurl \ + -lraptorbase \ + -lrdfutil_s \ + -lmsgbaseutil \ + -lgmbasegtk \ + $(TK_LIBS) \ + -lxpcom \ + -lreg \ + -lappcores \ + -lnetlib \ + -lnetwork \ + -lhttpurl \ + -lftpurl \ + -lgophurl \ + -labouturl \ + -lfileurl \ + -lremoturl \ + -lnetcnvts \ + -lmimetype \ + -lsockstuburl \ + -lnetutil \ + -lpwcac \ + -lnetcache \ + -lpref \ + -lsecfree \ + $(ZLIB_LIBS) \ + $(NSPR_LIBS) \ + -L$(DIST)/bin \ + -L$(DIST)/lib \ + $(NULL) + +include $(topsrcdir)/config/rules.mk + +$(LIBRARY) $(SHARED_LIBRARY): $(SHARED_LIBRARY_LIBS) Makefile.in + diff --git a/mailnews/addrbook/build/makefile.win b/mailnews/addrbook/build/makefile.win new file mode 100644 index 000000000000..d99e9a0dc251 --- /dev/null +++ b/mailnews/addrbook/build/makefile.win @@ -0,0 +1,68 @@ +#!gmake +# +# 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. + +DEPTH=..\..\.. +MODULE=mailnews + +MAKE_OBJ_TYPE=DLL +DLLNAME=addrbook +DLL=.\$(OBJDIR)\$(DLLNAME).dll +EXPORTS= \ + nsAbBaseCID.h \ + $(NULL) + +CPPSRCS= \ + nsAbFactory.cpp \ + +CPP_OBJS=\ + .\$(OBJDIR)\nsAbFactory.obj \ + $(NULL) +# XXX linking in raptor is a heinous crime that will go away once we +# have a more DOM-based mechanism for constructing elements and +# hooking in to their changes. + +LLIBS=\ + $(DIST)\lib\xpcom32.lib \ + $(DIST)\lib\msgcoreutil.lib \ + $(DIST)\lib\addrbook.lib \ + $(LIBNSPR) \ + $(DIST)\lib\plc3.lib \ + $(DIST)\lib\raptorbase.lib \ + $(DIST)\lib\rdfutil_s.lib \ + $(NULL) + +MISCDEP=$(LLIBS) + +# XXX Note dependencies on implementation dirs for factory methods. + +LINCS= -I$(DEPTH)\mailnews\local\src \ + -I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\mailnews \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\rdf \ + -I$(PUBLIC)\rdfutil \ + -I$(PUBLIC)\netlib \ + -I$(PUBLIC)\mime \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +install:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components + +clobber:: + rm -f $(DIST)\bin\components\$(DLLNAME) diff --git a/mailnews/addrbook/build/nsAbBaseCID.h b/mailnews/addrbook/build/nsAbBaseCID.h new file mode 100644 index 000000000000..3d2559f9b279 --- /dev/null +++ b/mailnews/addrbook/build/nsAbBaseCID.h @@ -0,0 +1,50 @@ +/* -*- 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 "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 nsAbBaseCID_h__ +#define nsAbBaseCID_h__ + +#include "nsISupports.h" +#include "nsIFactory.h" +#include "nsIComponentManager.h" + +#define NS_ABDIRECTORYDATASOURCE_CID \ +{ /* 0A79186D-F754-11d2-A2DA-001083003D0C */ \ + 0xa79186d, 0xf754, 0x11d2, \ + {0xa2, 0xda, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \ +} + +#define NS_ABDIRECTORYRESOURCE_CID \ +{ /* {6C21831D-FCC2-11d2-A2E2-001083003D0C}*/ \ + 0x6c21831d, 0xfcc2, 0x11d2, \ + {0xa2, 0xe2, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \ +} + +#define NS_ABCARDDATASOURCE_CID \ +{ /* 1920E486-0709-11d3-A2EC-001083003D0C */ \ + 0x1920e486, 0x709, 0x11d3, \ + {0xa2, 0xec, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \ +} + +#define NS_ABCARDRESOURCE_CID \ +{ /* {1920E487-0709-11d3-A2EC-001083003D0C}*/ \ + 0x1920e487, 0x709, 0x11d3, \ + {0xa2, 0xec, 0x0, 0x10, 0x83, 0x0, 0x3d, 0xc} \ +} + +#endif // nsAbBaseCID_h__ diff --git a/mailnews/addrbook/build/nsAbFactory.cpp b/mailnews/addrbook/build/nsAbFactory.cpp new file mode 100644 index 000000000000..c7446bb380ed --- /dev/null +++ b/mailnews/addrbook/build/nsAbFactory.cpp @@ -0,0 +1,285 @@ +/* -*- 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 "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 "nsIFactory.h" +#include "nsISupports.h" +#include "msgCore.h" +#include "nsAbBaseCID.h" +#include "pratom.h" +#include "nsIComponentManager.h" +#include "nsIServiceManager.h" +#include "rdf.h" +#include "nsCRT.h" +#include "nsCOMPtr.h" + + +/* Include all of the interfaces our factory can generate components for */ + +#include "nsDirectoryDataSource.h" +#include "nsCardDataSource.h" +#include "nsAbDirectory.h" +#include "nsAbCard.h" + +static NS_DEFINE_CID(kComponentManagerCID, NS_COMPONENTMANAGER_CID); + +static NS_DEFINE_CID(kAbDirectoryDataSourceCID, NS_ABDIRECTORYDATASOURCE_CID); +static NS_DEFINE_CID(kAbDirectoryCID, NS_ABDIRECTORYRESOURCE_CID); +static NS_DEFINE_CID(kAbCardDataSourceCID, NS_ABCARDDATASOURCE_CID); +static NS_DEFINE_CID(kAbCardCID, NS_ABCARDRESOURCE_CID); + +//////////////////////////////////////////////////////////// +// +//////////////////////////////////////////////////////////// +static PRInt32 g_InstanceCount = 0; +static PRInt32 g_LockCount = 0; + +class nsAbFactory : public nsIFactory +{ +public: + // nsISupports methods + NS_DECL_ISUPPORTS + + nsAbFactory(const nsCID &aClass, const char* aClassName, const char* aProgID); + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult); + NS_IMETHOD LockFactory(PRBool aLock); + +protected: + virtual ~nsAbFactory(); + + nsCID mClassID; + char* mClassName; + char* mProgID; + +// nsIServiceManager* mServiceManager; +}; + +nsAbFactory::nsAbFactory(const nsCID &aClass, const char* aClassName, const char* aProgID) + : mClassID(aClass), mClassName(nsCRT::strdup(aClassName)), mProgID(nsCRT::strdup(aProgID)) +{ + NS_INIT_REFCNT(); + // store a copy of the +// compMgrSupports->QueryInterface(nsIServiceManager::GetIID(), +// (void **)&mServiceManager); +} + +nsAbFactory::~nsAbFactory() +{ + NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); +// NS_IF_RELEASE(mServiceManager); + PL_strfree(mClassName); + PL_strfree(mProgID); +} + +nsresult nsAbFactory::QueryInterface(const nsIID &aIID, void **aResult) +{ + if (aResult == NULL) + return NS_ERROR_NULL_POINTER; + + // Always NULL result, in case of failure + *aResult = NULL; + + // we support two interfaces....nsISupports and nsFactory..... + if (aIID.Equals(::nsISupports::GetIID())) + *aResult = (void *)(nsISupports*)this; + else if (aIID.Equals(nsIFactory::GetIID())) + *aResult = (void *)(nsIFactory*)this; + + if (*aResult == NULL) + return NS_NOINTERFACE; + + AddRef(); // Increase reference count for caller + return NS_OK; +} + + +NS_IMPL_ADDREF(nsAbFactory) +NS_IMPL_RELEASE(nsAbFactory) + +nsresult nsAbFactory::CreateInstance(nsISupports *aOuter, const nsIID &aIID, void **aResult) +{ + if (aResult == NULL) + return NS_ERROR_NULL_POINTER; + + *aResult = NULL; + + // ClassID check happens here + // Whenever you add a new class that supports an interface, plug it in here!!! + + if (mClassID.Equals(kAbDirectoryDataSourceCID)) + { + nsresult rv; + nsABDirectoryDataSource * directoryDataSource = new nsABDirectoryDataSource(); + if (directoryDataSource) + rv = directoryDataSource->QueryInterface(aIID, aResult); + else + rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv) && directoryDataSource) + delete directoryDataSource; + return rv; + } + else if (mClassID.Equals(kAbDirectoryCID)) + { + nsresult rv; + nsABDirectory * directory = new nsABDirectory(); + if (directory) + rv = directory->QueryInterface(aIID, aResult); + else + rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv) && directory) + delete directory; + return rv; + } + if (mClassID.Equals(kAbCardDataSourceCID)) + { + nsresult rv; + nsABCardDataSource * cardDataSource = new nsABCardDataSource(); + if (cardDataSource) + rv = cardDataSource->QueryInterface(aIID, aResult); + else + rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv) && cardDataSource) + delete cardDataSource; + return rv; + } + else if (mClassID.Equals(kAbCardCID)) + { + nsresult rv; + nsABCard * card = new nsABCard(); + if (card) + rv = card->QueryInterface(aIID, aResult); + else + rv = NS_ERROR_OUT_OF_MEMORY; + + if (NS_FAILED(rv) && card) + delete card; + return rv; + } + return NS_NOINTERFACE; +} + +nsresult nsAbFactory::LockFactory(PRBool aLock) +{ + if (aLock) + PR_AtomicIncrement(&g_LockCount); + else + PR_AtomicDecrement(&g_LockCount); + + return NS_OK; +} + +// return the proper factory to the caller. +extern "C" NS_EXPORT nsresult NSGetFactory(nsISupports* aServMgr, + const nsCID &aClass, + const char *aClassName, + const char *aProgID, + nsIFactory **aFactory) +{ + if (nsnull == aFactory) + return NS_ERROR_NULL_POINTER; + + *aFactory = new nsAbFactory(aClass, aClassName, aProgID); + + if (aFactory) + return (*aFactory)->QueryInterface(nsIFactory::GetIID(), (void**)aFactory); // they want a Factory Interface so give it to them + else + return NS_ERROR_OUT_OF_MEMORY; +} + +extern "C" NS_EXPORT PRBool NSCanUnload(nsISupports* aServMgr) +{ + return PRBool(g_InstanceCount == 0 && g_LockCount == 0); +} + +extern "C" NS_EXPORT nsresult +NSRegisterSelf(nsISupports* aServMgr, const char* path) +{ + nsresult rv; + + nsCOMPtr servMgr(do_QueryInterface(aServMgr, &rv)); + if (NS_FAILED(rv)) return rv; + + nsIComponentManager* compMgr; + rv = servMgr->GetService(kComponentManagerCID, + nsIComponentManager::GetIID(), + (nsISupports**)&compMgr); + if (NS_FAILED(rv)) return rv; + + // register our RDF datasources: + rv = compMgr->RegisterComponent(kAbDirectoryDataSourceCID, + "Mail/News Address Book Directory Data Source", + NS_RDF_DATASOURCE_PROGID_PREFIX "addressdirectory", + path, PR_TRUE, PR_TRUE); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->RegisterComponent(kAbDirectoryCID, + "Mail/News Address Book Directory Factory", + NS_RDF_RESOURCE_FACTORY_PROGID_PREFIX "abdirectory", + path, PR_TRUE, PR_TRUE); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->RegisterComponent(kAbCardDataSourceCID, + "Mail/News Address Book Card Data Source", + NS_RDF_DATASOURCE_PROGID_PREFIX "addresscard", + path, PR_TRUE, PR_TRUE); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->RegisterComponent(kAbCardCID, + "Mail/News Address Book Card Factory", + NS_RDF_RESOURCE_FACTORY_PROGID_PREFIX "abcard", + path, PR_TRUE, PR_TRUE); + if (NS_FAILED(rv)) goto done; + done: + (void)servMgr->ReleaseService(kComponentManagerCID, compMgr); + return rv; +} + +extern "C" NS_EXPORT nsresult +NSUnregisterSelf(nsISupports* aServMgr, const char* path) +{ + nsresult rv; + + nsCOMPtr servMgr(do_QueryInterface(aServMgr, &rv)); + if (NS_FAILED(rv)) return rv; + + nsIComponentManager* compMgr; + rv = servMgr->GetService(kComponentManagerCID, + nsIComponentManager::GetIID(), + (nsISupports**)&compMgr); + if (NS_FAILED(rv)) return rv; + + rv = compMgr->UnregisterComponent(kAbDirectoryDataSourceCID, path); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->UnregisterComponent(kAbDirectoryCID, path); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->UnregisterComponent(kAbCardDataSourceCID, path); + if (NS_FAILED(rv)) goto done; + + rv = compMgr->UnregisterComponent(kAbCardCID, path); + if (NS_FAILED(rv)) goto done; + +done: + (void)servMgr->ReleaseService(kComponentManagerCID, compMgr); + return rv; +} diff --git a/mailnews/addrbook/makefile.win b/mailnews/addrbook/makefile.win new file mode 100644 index 000000000000..3cece3fdbff7 --- /dev/null +++ b/mailnews/addrbook/makefile.win @@ -0,0 +1,22 @@ +#!nmake +# +# 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. + +DEPTH=..\.. + +DIRS=public src build + +include <$(DEPTH)\config\rules.mak> diff --git a/mailnews/addrbook/public/Makefile.in b/mailnews/addrbook/public/Makefile.in new file mode 100644 index 000000000000..3d163e369536 --- /dev/null +++ b/mailnews/addrbook/public/Makefile.in @@ -0,0 +1,43 @@ +#!gmake +# +# 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. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ +MODULE = mailnews + +include $(DEPTH)/config/autoconf.mk +NO_GEN_XPT=1 +XPIDLSRCS = \ + nsIAbBase.idl \ + nsIAbListener.idl \ + nsIAbDirectory.idl \ + nsIAbCard.idl \ + $(NULL) + +EXPORTS = \ + nsIAbBase.h \ + nsIAbListener.h \ + nsIAbDirectory.h \ + nsIAbCard.h \ + $(NULL) + +include $(topsrcdir)/config/config.mk + +include $(topsrcdir)/config/rules.mk + diff --git a/mailnews/addrbook/public/makefile.win b/mailnews/addrbook/public/makefile.win new file mode 100644 index 000000000000..41bfa60e30eb --- /dev/null +++ b/mailnews/addrbook/public/makefile.win @@ -0,0 +1,39 @@ +#!nmake +# +# 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. + +DEPTH=..\..\.. +IGNORE_MANIFEST=1 + + +IDLSRCS = \ + nsIAbBase.idl \ + nsIAbListener.idl \ + nsIAbDirectory.idl \ + nsIAbCard.idl \ + $(NULL) + +EXPORTS = \ + nsIAbBase.h \ + nsIAbListener.h \ + nsIAbDirectory.h \ + nsIAbCard.h \ + $(NULL) + +MODULE=mailnews + +include <$(DEPTH)\config\rules.mak> + diff --git a/mailnews/addrbook/public/nsIAbBase.h b/mailnews/addrbook/public/nsIAbBase.h new file mode 100644 index 000000000000..e666defaea94 --- /dev/null +++ b/mailnews/addrbook/public/nsIAbBase.h @@ -0,0 +1,65 @@ +/* + * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIAbBase.idl + */ + +#ifndef __gen_nsIAbBase_h__ +#define __gen_nsIAbBase_h__ + +#include "nsISupports.h" /* interface nsISupports */ +#include "nsICollection.h" /* interface nsICollection */ +#include "nsIEnumerator.h" /* interface nsIEnumerator */ +#include "nsIAbListener.h" /* interface nsIAbListener */ + +#ifdef XPIDL_JS_STUBS +#include "jsapi.h" +#endif +class nsIAbListener; /* forward decl */ + +/* starting interface: nsIAbBase */ + +/* {013DD009-F73B-11d2-A2DA-001083003D0C} */ +#define NS_IABBASE_IID_STR "013DD009-F73B-11d2-A2DA-001083003D0C" +#define NS_IABBASE_IID \ + {0x013DD009, 0xF73B, 0x11d2, \ + { 0xA2, 0xDA, 0x00, 0x10, 0x83, 0x00, 0x3D, 0x0C }} + +class nsIAbBase : public nsICollection { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABBASE_IID) + + /* readonly attribute string URI; */ + NS_IMETHOD GetURI(char * *aURI) = 0; + + /* attribute string name; */ + NS_IMETHOD GetName(char * *aName) = 0; + NS_IMETHOD SetName(char * aName) = 0; + + /* nsISupports GetChildNamed (in string name); */ + NS_IMETHOD GetChildNamed(const char *name, nsISupports **_retval) = 0; + + /* attribute nsIAbBase parent; */ + NS_IMETHOD GetParent(nsIAbBase * *aParent) = 0; + NS_IMETHOD SetParent(nsIAbBase * aParent) = 0; + + /* nsIEnumerator GetChildNodes (); */ + NS_IMETHOD GetChildNodes(nsIEnumerator **_retval) = 0; + + /* void AddAddrBookListener (in nsIAbListener listener); */ + NS_IMETHOD AddAddrBookListener(nsIAbListener *listener) = 0; + + /* void RemoveAddrBookListener (in nsIAbListener listener); */ + NS_IMETHOD RemoveAddrBookListener(nsIAbListener *listener) = 0; + + /* void AddUnique (in nsISupports element); */ + NS_IMETHOD AddUnique(nsISupports *element) = 0; + + /* void ReplaceElement (in nsISupports element, in nsISupports newElement); */ + NS_IMETHOD ReplaceElement(nsISupports *element, nsISupports *newElement) = 0; + +#ifdef XPIDL_JS_STUBS + static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx); + static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIAbBase *priv); +#endif +}; + +#endif /* __gen_nsIAbBase_h__ */ diff --git a/mailnews/addrbook/public/nsIAbBase.idl b/mailnews/addrbook/public/nsIAbBase.idl new file mode 100644 index 000000000000..09f168e3fafa --- /dev/null +++ b/mailnews/addrbook/public/nsIAbBase.idl @@ -0,0 +1,41 @@ +/* -*- 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 "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 "nsICollection.idl" +#include "nsIAbListener.idl" + +interface nsIAbListener; + +[uuid(013DD009-F73B-11d2-A2DA-001083003D0C)] +interface nsIAbBase : nsICollection { + + readonly attribute string URI; + attribute string name; + + nsISupports GetChildNamed(in string name); + attribute nsIAbBase parent; + + nsIEnumerator GetChildNodes(); + + void AddAddrBookListener(in nsIAbListener listener); + void RemoveAddrBookListener(in nsIAbListener listener); + + void AddUnique(in nsISupports element); + void ReplaceElement(in nsISupports element, in nsISupports newElement); + +}; diff --git a/mailnews/addrbook/public/nsIAbCard.h b/mailnews/addrbook/public/nsIAbCard.h new file mode 100644 index 000000000000..92a5a4b54376 --- /dev/null +++ b/mailnews/addrbook/public/nsIAbCard.h @@ -0,0 +1,64 @@ +/* + * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIAbCard.idl + */ + +#ifndef __gen_nsIAbCard_h__ +#define __gen_nsIAbCard_h__ + +#include "nsISupports.h" /* interface nsISupports */ +#include "nsIAbBase.h" /* interface nsIAbBase */ +#include "nsICollection.h" /* interface nsICollection */ +#include "nsIEnumerator.h" /* interface nsIEnumerator */ +#include "nsIAbListener.h" /* interface nsIAbListener */ + +#ifdef XPIDL_JS_STUBS +#include "jsapi.h" +#endif + +/* starting interface: nsIAbCard */ + +/* {FA5C977F-04C8-11d3-A2EB-001083003D0C} */ +#define NS_IABCARD_IID_STR "FA5C977F-04C8-11d3-A2EB-001083003D0C" +#define NS_IABCARD_IID \ + {0xFA5C977F, 0x04C8, 0x11d3, \ + { 0xA2, 0xEB, 0x00, 0x10, 0x83, 0x00, 0x3D, 0x0C }} + +class nsIAbCard : public nsIAbBase { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABCARD_IID) + + /* attribute string personName; */ + NS_IMETHOD GetPersonName(char * *aPersonName) = 0; + NS_IMETHOD SetPersonName(char * aPersonName) = 0; + + /* attribute string listName; */ + NS_IMETHOD GetListName(char * *aListName) = 0; + NS_IMETHOD SetListName(char * aListName) = 0; + + /* attribute string email; */ + NS_IMETHOD GetEmail(char * *aEmail) = 0; + NS_IMETHOD SetEmail(char * aEmail) = 0; + + /* attribute string workPhone; */ + NS_IMETHOD GetWorkPhone(char * *aWorkPhone) = 0; + NS_IMETHOD SetWorkPhone(char * aWorkPhone) = 0; + + /* attribute string city; */ + NS_IMETHOD GetCity(char * *aCity) = 0; + NS_IMETHOD SetCity(char * aCity) = 0; + + /* attribute string organization; */ + NS_IMETHOD GetOrganization(char * *aOrganization) = 0; + NS_IMETHOD SetOrganization(char * aOrganization) = 0; + + /* attribute string nickname; */ + NS_IMETHOD GetNickname(char * *aNickname) = 0; + NS_IMETHOD SetNickname(char * aNickname) = 0; + +#ifdef XPIDL_JS_STUBS + static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx); + static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIAbCard *priv); +#endif +}; + +#endif /* __gen_nsIAbCard_h__ */ diff --git a/mailnews/addrbook/public/nsIAbCard.idl b/mailnews/addrbook/public/nsIAbCard.idl new file mode 100644 index 000000000000..ee855ac65581 --- /dev/null +++ b/mailnews/addrbook/public/nsIAbCard.idl @@ -0,0 +1,31 @@ +/* -*- 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 "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 "nsIAbBase.idl" + +[uuid(FA5C977F-04C8-11d3-A2EB-001083003D0C)] +interface nsIAbCard : nsIAbBase { + + attribute string personName; + attribute string listName; + attribute string email; + attribute string workPhone; + attribute string city; + attribute string organization; + attribute string nickname; +}; diff --git a/mailnews/addrbook/public/nsIAbDirectory.h b/mailnews/addrbook/public/nsIAbDirectory.h new file mode 100644 index 000000000000..b4e1ed966bce --- /dev/null +++ b/mailnews/addrbook/public/nsIAbDirectory.h @@ -0,0 +1,43 @@ +/* + * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIAbDirectory.idl + */ + +#ifndef __gen_nsIAbDirectory_h__ +#define __gen_nsIAbDirectory_h__ + +#include "nsISupports.h" /* interface nsISupports */ +#include "nsIAbBase.h" /* interface nsIAbBase */ +#include "nsICollection.h" /* interface nsICollection */ +#include "nsIEnumerator.h" /* interface nsIEnumerator */ +#include "nsIAbCard.h" /* interface nsIAbCard */ +#include "nsIAbListener.h" /* interface nsIAbListener */ + +#ifdef XPIDL_JS_STUBS +#include "jsapi.h" +#endif + +/* starting interface: nsIAbDirectory */ + +/* {1920E485-0709-11d3-A2EC-001083003D0C} */ +#define NS_IABDIRECTORY_IID_STR "1920E485-0709-11d3-A2EC-001083003D0C" +#define NS_IABDIRECTORY_IID \ + {0x1920E485, 0x0709, 0x11d3, \ + { 0xA2, 0xEC, 0x00, 0x10, 0x83, 0x00, 0x3D, 0x0C }} + +class nsIAbDirectory : public nsIAbBase { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABDIRECTORY_IID) + + /* nsIEnumerator GetChildCards (); */ + NS_IMETHOD GetChildCards(nsIEnumerator **_retval) = 0; + + /* nsIAbCard CreateCardFromDirectory (); */ + NS_IMETHOD CreateCardFromDirectory(nsIAbCard **_retval) = 0; + +#ifdef XPIDL_JS_STUBS + static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx); + static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIAbDirectory *priv); +#endif +}; + +#endif /* __gen_nsIAbDirectory_h__ */ diff --git a/mailnews/addrbook/public/nsIAbDirectory.idl b/mailnews/addrbook/public/nsIAbDirectory.idl new file mode 100644 index 000000000000..8108198b1ba8 --- /dev/null +++ b/mailnews/addrbook/public/nsIAbDirectory.idl @@ -0,0 +1,28 @@ +/* -*- 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 "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 "nsIAbBase.idl" +#include "nsIAbCard.idl" + +[uuid(1920E485-0709-11d3-A2EC-001083003D0C)] +interface nsIAbDirectory : nsIAbBase { + + nsIEnumerator GetChildCards(); + + nsIAbCard CreateCardFromDirectory(); +}; diff --git a/mailnews/addrbook/public/nsIAbListener.h b/mailnews/addrbook/public/nsIAbListener.h new file mode 100644 index 000000000000..e453c73b2bfb --- /dev/null +++ b/mailnews/addrbook/public/nsIAbListener.h @@ -0,0 +1,45 @@ +/* + * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIAbListener.idl + */ + +#ifndef __gen_nsIAbListener_h__ +#define __gen_nsIAbListener_h__ + +#include "nsISupports.h" /* interface nsISupports */ +#include "nsIAbBase.h" /* interface nsIAbBase */ +#include "nsICollection.h" /* interface nsICollection */ +#include "nsIEnumerator.h" /* interface nsIEnumerator */ + +#ifdef XPIDL_JS_STUBS +#include "jsapi.h" +#endif +class nsIAbBase; /* forward decl */ + +/* starting interface: nsIAbListener */ + +/* {1920E484-0709-11d3-A2EC-001083003D0C} */ +#define NS_IABLISTENER_IID_STR "1920E484-0709-11d3-A2EC-001083003D0C" +#define NS_IABLISTENER_IID \ + {0x1920E484, 0x0709, 0x11d3, \ + { 0xA2, 0xEC, 0x00, 0x10, 0x83, 0x00, 0x3D, 0x0C }} + +class nsIAbListener : public nsISupports { + public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IABLISTENER_IID) + + /* void OnItemAdded (in nsIAbBase parentDir, in nsISupports item); */ + NS_IMETHOD OnItemAdded(nsIAbBase *parentDir, nsISupports *item) = 0; + + /* void OnItemRemoved (in nsIAbBase parentDir, in nsISupports item); */ + NS_IMETHOD OnItemRemoved(nsIAbBase *parentDir, nsISupports *item) = 0; + + /* void OnItemPropertyChanged (in nsISupports item, in string property, in string oldValue, in string newValue); */ + NS_IMETHOD OnItemPropertyChanged(nsISupports *item, const char *property, const char *oldValue, const char *newValue) = 0; + +#ifdef XPIDL_JS_STUBS + static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx); + static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIAbListener *priv); +#endif +}; + +#endif /* __gen_nsIAbListener_h__ */ diff --git a/mailnews/addrbook/public/nsIAbListener.idl b/mailnews/addrbook/public/nsIAbListener.idl new file mode 100644 index 000000000000..62008ed4c850 --- /dev/null +++ b/mailnews/addrbook/public/nsIAbListener.idl @@ -0,0 +1,32 @@ +/* -*- 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 "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 "nsISupports.idl" +#include "nsIEnumerator.idl" +#include "nsIAbBase.idl" + +interface nsIAbBase; + +[uuid(1920E484-0709-11d3-A2EC-001083003D0C)] +interface nsIAbListener : nsISupports { + + void OnItemAdded(in nsIAbBase parentDir, in nsISupports item); + void OnItemRemoved(in nsIAbBase parentDir, in nsISupports item); + void OnItemPropertyChanged(in nsISupports item, in string property, in string oldValue, in string newValue); + +}; diff --git a/mailnews/addrbook/src/Makefile.in b/mailnews/addrbook/src/Makefile.in new file mode 100644 index 000000000000..56b7d232eb97 --- /dev/null +++ b/mailnews/addrbook/src/Makefile.in @@ -0,0 +1,43 @@ +#!gmake +# +# 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. + +DEPTH = ../../.. +topsrcdir = @top_srcdir@ +VPATH = @srcdir@ +srcdir = @srcdir@ + +include $(DEPTH)/config/autoconf.mk + +MODULE=mailnewsaddrbook +LIBRARY_NAME=mailnewsaddrbook_s + +EXPORTS = \ + $(NULL) + +CPPSRCS = \ + nsDirectoryDataSource.cpp \ + nsAbdirectory.cpp \ + nsCardDataSource.cpp \ + nsAbCard.cpp \ + $(NULL) + +# we don't want the shared lib, but we want to force the creation of a static lib. +override NO_SHARED_LIB=1 +override NO_STATIC_LIB= + +include $(topsrcdir)/config/rules.mk + diff --git a/mailnews/addrbook/src/makefile.win b/mailnews/addrbook/src/makefile.win new file mode 100644 index 000000000000..9cf4b03b34d9 --- /dev/null +++ b/mailnews/addrbook/src/makefile.win @@ -0,0 +1,79 @@ +#!nmake +# +# 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. + +DEPTH=..\..\.. +IGNORE_MANIFEST=1 + +include <$(DEPTH)\config\config.mak> + +LIBRARY_NAME=addrbook +MODULE= mailnews +REQUIRES=xpcom nspr rdf + +DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN + +CPPSRCS= \ + nsDirectoryDataSource.cpp \ + nsAbDirectory.cpp \ + nsCardDataSource.cpp \ + nsAbCard.cpp \ + $(NULL) + + + +CPP_OBJS= \ + .\$(OBJDIR)\nsDirectoryDataSource.obj \ + .\$(OBJDIR)\nsAbDirectory.obj \ + .\$(OBJDIR)\nsCardDataSource.obj \ + .\$(OBJDIR)\nsAbCard.obj \ + $(NULL) + + +EXPORTS= \ + nsDirectoryDataSource.h \ + nsAbDirectory.h \ + nsCardDataSource.h \ + nsAbCard.h \ + $(NULL) + +LINCS= \ + -I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\mailnews \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\rdf \ + -I$(PUBLIC)\rdfutil \ + -I$(PUBLIC)\pref \ + -I$(PUBLIC)\js \ + -I$(PUBLIC)\netlib \ + -I$(PUBLIC)\dom \ + -I$(PUBLIC)\appcores \ + -I$(PUBLIC)\security \ + -I$(PUBLIC)\mime \ + $(NULL) + +LCFLAGS = \ + $(LCFLAGS) \ + $(DEFINES) \ + $(NULL) + +include <$(DEPTH)\config\rules.mak> + +libs:: $(LIBRARY) + $(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib + +clobber:: + rm -f $(DIST)\lib\$(LIBRARY_NAME).lib diff --git a/mailnews/addrbook/src/nsAbCard.cpp b/mailnews/addrbook/src/nsAbCard.cpp new file mode 100644 index 000000000000..a3f065906113 --- /dev/null +++ b/mailnews/addrbook/src/nsAbCard.cpp @@ -0,0 +1,550 @@ +/* -*- 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 "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 "msgCore.h" // precompiled header... + +#include "nsABCard.h" +#include "nsIRDFService.h" +#include "nsIServiceManager.h" +#include "nsRDFCID.h" +#include "nsXPIDLString.h" +#include "nsCOMPtr.h" + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); + + +// we need this because of an egcs 1.0 (and possibly gcc) compiler bug +// that doesn't allow you to call ::nsISupports::GetIID() inside of a class +// that multiply inherits from nsISupports +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsABCard::nsABCard(void) + : nsRDFResource(), mListeners(nsnull), + mCsid(0), mDepth(0), mPrefFlags(0), + mInitialized(PR_FALSE) +{ +// NS_INIT_REFCNT(); done by superclass + + NS_NewISupportsArray(getter_AddRefs(mSubDirectories)); + + //The rdf:addresscard datasource is going to be a listener to all nsIMsgFolders, so add + //it as a listener + nsresult rv; + NS_WITH_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr datasource; + rv = rdfService->GetDataSource("rdf:addresscard", getter_AddRefs(datasource)); + if(NS_SUCCEEDED(rv)) + { + nsCOMPtr directoryListener(do_QueryInterface(datasource, &rv)); + if(NS_SUCCEEDED(rv)) + { + AddAddrBookListener(directoryListener); + } + } + } +} + +nsABCard::~nsABCard(void) +{ + if(mSubDirectories) + { + PRUint32 count; + nsresult rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + + for (int i = count - 1; i >= 0; i--) + mSubDirectories->RemoveElementAt(i); + } + + if (mListeners) + { + for (PRInt32 i = mListeners->Count() - 1; i >= 0; --i) + mListeners->RemoveElementAt(i); + delete mListeners; + } +} + +NS_IMPL_ISUPPORTS_INHERITED(nsABCard, nsRDFResource, nsIAbCard) + +//////////////////////////////////////////////////////////////////////////////// + +typedef PRBool +(*nsArrayFilter)(nsISupports* element, void* data); + +static nsresult +nsFilterBy(nsISupportsArray* array, nsArrayFilter filter, void* data, + nsISupportsArray* *result) +{ + nsCOMPtr f; + nsresult rv = NS_NewISupportsArray(getter_AddRefs(f)); + if (NS_FAILED(rv)) return rv; + PRUint32 count; + rv = array->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr element = getter_AddRefs((*array)[i]); + if (filter(element, data)) { + rv = f->AppendElement(element); + if (NS_FAILED(rv)) { + return rv; + } + } + } + *result = f; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsABCard::AddUnique(nsISupports* element) +{ + // XXX fix this + return mSubDirectories->AppendElement(element); +} + +NS_IMETHODIMP +nsABCard::ReplaceElement(nsISupports* element, nsISupports* newElement) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsABCard::GetChildNodes(nsIEnumerator* *result) +{ + if (!mInitialized) + { + if (!PL_strcmp(mURI, "abcard://Pab1/Card1") || + !PL_strcmp(mURI, "abcard://Pab1/Card2") || + !PL_strcmp(mURI, "abcard://Pab2/Card1") || + !PL_strcmp(mURI, "abcard://Pab2/Card2") || + !PL_strcmp(mURI, "abcard://Pab3/Card1") || + !PL_strcmp(mURI, "abcard://Pab3/Card2")) + { + for (int i= 0; i < 6; i++) + { + nsCOMPtr card; + if (i == 0) + AddSubNode("PersonName", getter_AddRefs(card)); + if (i == 1) + AddSubNode("Email", getter_AddRefs(card)); + if (i == 2) + AddSubNode("WorkPhone", getter_AddRefs(card)); + if (i == 3) + AddSubNode("Organization", getter_AddRefs(card)); + if (i == 4) + AddSubNode("Nickname", getter_AddRefs(card)); + if (i == 5) + AddSubNode("City", getter_AddRefs(card)); + } + } + mInitialized = PR_TRUE; + } + return mSubDirectories->Enumerate(result); +} + +nsresult nsABCard::AddSubNode(nsAutoString name, nsIAbCard **childCard) +{ + if(!childCard) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); + + if(NS_FAILED(rv)) + return rv; + + nsAutoString uri; + uri.Append(mURI); + uri.Append('/'); + + uri.Append(name); + char* uriStr = uri.ToNewCString(); + if (uriStr == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr res; + rv = rdf->GetResource(uriStr, getter_AddRefs(res)); + if (NS_FAILED(rv)) + return rv; + nsCOMPtr card(do_QueryInterface(res, &rv)); + if (NS_FAILED(rv)) + return rv; + delete[] uriStr; + + mSubDirectories->AppendElement(card); + *childCard = card; + NS_ADDREF(*childCard); + + (void)nsServiceManager::ReleaseService(kRDFServiceCID, rdf); + + return rv; +} + +NS_IMETHODIMP nsABCard::AddAddrBookListener(nsIAbListener * listener) +{ + if (! mListeners) + { + mListeners = new nsVoidArray(); + if(!mListeners) + return NS_ERROR_OUT_OF_MEMORY; + } + mListeners->AppendElement(listener); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::RemoveAddrBookListener(nsIAbListener * listener) +{ + if (! mListeners) + return NS_OK; + mListeners->RemoveElement(listener); + return NS_OK; + +} + +NS_IMETHODIMP nsABCard::GetPersonName(char **name) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("John"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("Mary"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("Lisa"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("Frank"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("Teri"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("Ted"); + *name = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetListName(char **listname) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("John"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("Mary"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("Lisa"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("Frank"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("Teri"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("Ted"); + *listname = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetEmail(char **email) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("john@foo.com"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("mary@foo.com"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("lisa@foo.com"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("frank@foo.com"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("teri@foo.com"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("ted@foo.com"); + *email = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetCity(char **city) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("Mountian View"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("San Francisco"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("San Jose"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("San Jose"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("Sunnyvale"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("Sunnyvale"); + *city = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetOrganization(char **organization) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("Market"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("Sales"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("Engineer"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("Finance"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("Human Resource"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("Payroll"); + *organization = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetWorkPhone(char **workphone) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("1111"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("6666"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("2222"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("4444"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("7777"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("3333"); + *workphone = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetNickname(char **nickname) +{ + nsString tempName; + if (!PL_strcmp(mURI, "abcard://Pab1/Card1")) + tempName.Append("John"); + if (!PL_strcmp(mURI, "abcard://Pab1/Card2")) + tempName.Append("Mary"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card1")) + tempName.Append("Lisa"); + if (!PL_strcmp(mURI, "abcard://Pab2/Card2")) + tempName.Append("Frank"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card1")) + tempName.Append("Teri"); + if (!PL_strcmp(mURI, "abcard://Pab3/Card2")) + tempName.Append("Ted"); + *nickname = tempName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::SetPersonName(char * aPersonName) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetListName(char * aListName) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetEmail(char * aEmail) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetWorkPhone(char * aWorkPhone) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetCity(char * aCity) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetOrganization(char * aOrganization) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetNickname(char * aNickname) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP_(PRUint32) nsABCard::Count(void) const +{ + PRUint32 count; + nsresult rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + return count; +} + +NS_IMETHODIMP nsABCard::AppendElement(nsISupports *aElement) +{ + return mSubDirectories->AppendElement(aElement); +} + +NS_IMETHODIMP nsABCard::RemoveElement(nsISupports *aElement) +{ + return mSubDirectories->RemoveElement(aElement); +} + + +NS_IMETHODIMP nsABCard::Enumerate(nsIEnumerator* *result) +{ + // nsABCard only have subfolders, no message elements + return mSubDirectories->Enumerate(result); +} + +NS_IMETHODIMP nsABCard::Clear(void) +{ + return mSubDirectories->Clear(); +} + +NS_IMETHODIMP nsABCard::GetName(char **name) +{ + SetName("Personal Address Book"); + *name = mCardName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABCard::SetName(char * name) +{ + mCardName = name; + return NS_OK; +} + +NS_IMETHODIMP nsABCard::GetParent(nsIAbBase* *parent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::SetParent(nsIAbBase *parent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::GetChildNamed(const char* name, nsISupports* *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCard::ContainsChildNamed(const char *name, PRBool* containsChild) +{ + nsCOMPtr child; + + if(containsChild) + { + *containsChild = PR_FALSE; + if(NS_SUCCEEDED(GetChildNamed(name, getter_AddRefs(child)))) + { + *containsChild = child != nsnull; + } + return NS_OK; + } + else + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP nsABCard::FindParentOf(nsIAbCard * aDirectory, nsIAbCard ** aParent) +{ + if(!aParent) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + *aParent = nsnull; + + PRUint32 count; + rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + nsCOMPtr supports; + nsCOMPtr child; + + for (PRUint32 i = 0; i < count && *aParent == NULL; i++) + { + supports = getter_AddRefs(mSubDirectories->ElementAt(i)); + child = do_QueryInterface(supports, &rv); + if(NS_SUCCEEDED(rv) && child) + { + if (aDirectory == child.get()) + { + *aParent = this; + NS_ADDREF(*aParent); + return NS_OK; + } + } + } + + for (PRUint32 j = 0; j < count && *aParent == NULL; j++) + { +/* + supports = getter_AddRefs(mSubDirectories->ElementAt(j)); + child = do_QueryInterface(supports, &rv); + if(NS_SUCCEEDED(rv) && child) + { + rv = child->FindParentOf(aDirectory, aParent); + if(NS_SUCCEEDED(rv)) + return rv; + } +*/ + } + + return rv; +} + +NS_IMETHODIMP nsABCard::IsParentOf(nsIAbCard *child, PRBool deep, PRBool *isParent) +{ + if(!isParent) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + PRUint32 count; + rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + + for (PRUint32 i = 0; i < count; i++) + { + nsCOMPtr supports = getter_AddRefs(mSubDirectories->ElementAt(i)); + nsCOMPtr directory(do_QueryInterface(supports, &rv)); + if(NS_SUCCEEDED(rv)) + { + if (directory.get() == child ) + *isParent = PR_TRUE; + else if(deep) + {; +// directory->IsParentOf(child, deep, isParent); + } + } + if(*isParent) + return NS_OK; + } + *isParent = PR_FALSE; + return rv; +} + + +#ifdef HAVE_DB +NS_IMETHOD GetTotalPersonsInDB(PRUint32 *totalPersons) const; // How many messages in database. +#endif + diff --git a/mailnews/addrbook/src/nsAbCard.h b/mailnews/addrbook/src/nsAbCard.h new file mode 100644 index 000000000000..eb2d33554816 --- /dev/null +++ b/mailnews/addrbook/src/nsAbCard.h @@ -0,0 +1,131 @@ +/* -*- 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 "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. + */ + +/******************************************************************************************************** + + Interface for representing Address Book Directory + +*********************************************************************************************************/ + +#ifndef nsABCard_h__ +#define nsABCard_h__ + +#include "msgCore.h" +#include "nsIAbCard.h" /* include the interface we are going to support */ +#include "nsRDFResource.h" +#include "nsISupportsArray.h" +#include "nsCOMPtr.h" + + /* + * Address Book Directory + */ + +class nsABCard: public nsRDFResource, public nsIAbCard +{ +public: + nsABCard(void); + virtual ~nsABCard(void); + + NS_DECL_ISUPPORTS_INHERITED + + // nsICollection methods: + NS_IMETHOD_(PRUint32) Count(void) const; + NS_IMETHOD AppendElement(nsISupports *aElement); + NS_IMETHOD RemoveElement(nsISupports *aElement); + NS_IMETHOD Enumerate(nsIEnumerator* *result); + NS_IMETHOD Clear(void); + + // nsIFolder methods: + NS_IMETHOD GetURI(char* *name) { return nsRDFResource::GetValue(name); } + NS_IMETHOD GetName(char **name); + NS_IMETHOD SetName(char *name); + NS_IMETHOD GetChildNamed(const char *name, nsISupports* *result); + NS_IMETHOD GetParent(nsIAbBase* *parent); + NS_IMETHOD SetParent(nsIAbBase *parent); + NS_IMETHOD GetChildNodes(nsIEnumerator* *result); + NS_IMETHOD AddAddrBookListener(nsIAbListener * listener); + NS_IMETHOD RemoveAddrBookListener(nsIAbListener * listener); + + + // nsIAbCard methods: + NS_IMETHOD AddUnique(nsISupports* element); + NS_IMETHOD ReplaceElement(nsISupports* element, nsISupports* newElement); + NS_IMETHOD GetPersonName(char * *personName); + NS_IMETHOD SetPersonName(char * personName); + NS_IMETHOD GetListName(char * *listName); + NS_IMETHOD SetListName(char * listName); + NS_IMETHOD GetEmail(char * *email); + NS_IMETHOD SetEmail(char * email); + NS_IMETHOD GetWorkPhone(char * *workPhone); + NS_IMETHOD SetWorkPhone(char * workPhone); + NS_IMETHOD GetCity(char * *city); + NS_IMETHOD SetCity(char * city); + NS_IMETHOD GetOrganization(char * *organization); + NS_IMETHOD SetOrganization(char * organization); + NS_IMETHOD GetNickname(char * *nickname); + NS_IMETHOD SetNickname(char * nickname); + +// NS_IMETHOD GetVisibleSubFolders(nsIEnumerator* *result); +// NS_IMETHOD GetPersons(nsIEnumerator ** threadEnumerator); + +// NS_IMETHOD GetPrettyName(char ** name); +// NS_IMETHOD SetPrettyName(char * name); +// NS_IMETHOD BuildDirectoryURL(char ** url); + + +// NS_IMETHOD GetPrettiestName(char ** name); + +// NS_IMETHOD OnCloseDirectory(); +// NS_IMETHOD Delete(); + + NS_IMETHODIMP ContainsChildNamed(const char *name, PRBool* containsChild); + NS_IMETHODIMP FindParentOf(nsIAbCard * aDirectory, nsIAbCard ** aParent); + NS_IMETHODIMP IsParentOf(nsIAbCard *child, PRBool deep, PRBool *isParent); + +// NS_IMETHOD CreateSubDirectory(const char *dirName); + +// NS_IMETHOD Rename(const char *name); + +// NS_IMETHOD GetDepth(PRUint32 *depth); +// NS_IMETHOD SetDepth(PRUint32 depth); + +#ifdef HAVE_DB + NS_IMETHOD GetTotalPersonsInDB(PRUint32 *totalPersons) const; // How many messages in database. +#endif + +protected: +// nsresult NotifyPropertyChanged(char *property, char* oldValue, char* newValue); +// nsresult NotifyItemAdded(nsISupports *item); +// nsresult NotifyItemDeleted(nsISupports *item); + + + nsresult AddSubNode(nsAutoString name, nsIAbCard **childDir); + +protected: + nsString mCardName; + nsCOMPtr mSubDirectories; + nsVoidArray *mListeners; + PRBool mInitialized; + + PRInt16 mCsid; // default csid for folder/newsgroup - maintained by fe. + PRUint8 mDepth; + PRInt32 mPrefFlags; // prefs like MSG_PREF_OFFLINE, MSG_PREF_ONE_PANE, etc + +}; + +#endif diff --git a/mailnews/addrbook/src/nsAbDirectory.cpp b/mailnews/addrbook/src/nsAbDirectory.cpp new file mode 100644 index 000000000000..73ef598ee886 --- /dev/null +++ b/mailnews/addrbook/src/nsAbDirectory.cpp @@ -0,0 +1,493 @@ +/* -*- 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 "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 "msgCore.h" // precompiled header... + +#include "nsAbDirectory.h" +#include "nsIRDFService.h" +#include "nsIServiceManager.h" +#include "nsRDFCID.h" +#include "nsXPIDLString.h" +#include "nsCOMPtr.h" +#include "nsAbBaseCID.h" +#include "nsAbCard.h" + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); + +static NS_DEFINE_CID(kAbCardCID, NS_ABCARDRESOURCE_CID); + +// we need this because of an egcs 1.0 (and possibly gcc) compiler bug +// that doesn't allow you to call ::nsISupports::GetIID() inside of a class +// that multiply inherits from nsISupports +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsABDirectory::nsABDirectory(void) + : nsRDFResource(), mListeners(nsnull), + mCsid(0), mDepth(0), mPrefFlags(0), + mInitialized(PR_FALSE), mCardInitialized(PR_FALSE) +{ +// NS_INIT_REFCNT(); done by superclass + + NS_NewISupportsArray(getter_AddRefs(mSubDirectories)); + NS_NewISupportsArray(getter_AddRefs(mSubCards)); + + //The rdf:addressdirectory datasource is going to be a listener to all nsIAbDirectory, so add + //it as a listener + nsresult rv; + NS_WITH_SERVICE(nsIRDFService, rdfService, kRDFServiceCID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr datasource; + rv = rdfService->GetDataSource("rdf:addressdirectory", getter_AddRefs(datasource)); + if(NS_SUCCEEDED(rv)) + { + nsCOMPtr directoryListener(do_QueryInterface(datasource, &rv)); + if(NS_SUCCEEDED(rv)) + { + AddAddrBookListener(directoryListener); + } + } + } +} + +nsABDirectory::~nsABDirectory(void) +{ + if(mSubDirectories) + { + PRUint32 count; + nsresult rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + + for (int i = count - 1; i >= 0; i--) + mSubDirectories->RemoveElementAt(i); + } + + if(mSubCards) + { + PRUint32 count; + nsresult rv = mSubCards->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + + for (int i = count - 1; i >= 0; i--) + mSubCards->RemoveElementAt(i); + } + + if (mListeners) + { + for (PRInt32 i = mListeners->Count() - 1; i >= 0; --i) + mListeners->RemoveElementAt(i); + delete mListeners; + } + +} + +NS_IMPL_ISUPPORTS_INHERITED(nsABDirectory, nsRDFResource, nsIAbDirectory) + +//////////////////////////////////////////////////////////////////////////////// + +typedef PRBool +(*nsArrayFilter)(nsISupports* element, void* data); + +static nsresult +nsFilterBy(nsISupportsArray* array, nsArrayFilter filter, void* data, + nsISupportsArray* *result) +{ + nsCOMPtr f; + nsresult rv = NS_NewISupportsArray(getter_AddRefs(f)); + if (NS_FAILED(rv)) return rv; + PRUint32 count; + rv = array->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + for (PRUint32 i = 0; i < count; i++) { + nsCOMPtr element = getter_AddRefs((*array)[i]); + if (filter(element, data)) { + rv = f->AppendElement(element); + if (NS_FAILED(rv)) { + return rv; + } + } + } + *result = f; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsABDirectory::AddUnique(nsISupports* element) +{ + // XXX fix this + return mSubDirectories->AppendElement(element); +} + +NS_IMETHODIMP +nsABDirectory::ReplaceElement(nsISupports* element, nsISupports* newElement) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsABDirectory::GetChildNodes(nsIEnumerator* *result) +{ + if (!mInitialized) + { + if (!PL_strcmp(mURI, "abdirectory:/")) + { + for (int i = 0; i < 3; i++) + { + nsCOMPtr childDir; + nsAutoString currentDirStr = "Pab"; + if (i == 0) currentDirStr.Append('1'); + if (i == 1) currentDirStr.Append('2'); + if (i == 2) currentDirStr.Append('3'); + AddSubDirectory(currentDirStr, getter_AddRefs(childDir)); + } + } + mInitialized = PR_TRUE; + } + return mSubDirectories->Enumerate(result); +} + +nsresult nsABDirectory::AddSubDirectory(nsAutoString name, nsIAbDirectory **childDir) +{ + if(!childDir) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); + + if(NS_FAILED(rv)) + return rv; + + nsAutoString uri; + uri.Append(mURI); + uri.Append("/"); + + uri.Append(name); + char* uriStr = uri.ToNewCString(); + if (uriStr == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr res; + rv = rdf->GetResource(uriStr, getter_AddRefs(res)); + if (NS_FAILED(rv)) + return rv; + nsCOMPtr directory(do_QueryInterface(res, &rv)); + if (NS_FAILED(rv)) + return rv; + delete[] uriStr; + + mSubDirectories->AppendElement(directory); + *childDir = directory; + NS_ADDREF(*childDir); + + (void)nsServiceManager::ReleaseService(kRDFServiceCID, rdf); + + return rv; +} + +NS_IMETHODIMP nsABDirectory::GetChildCards(nsIEnumerator* *result) +{ + if (!mCardInitialized) + { + if (!PL_strcmp(mURI, "abdirectory://Pab1") || + !PL_strcmp(mURI, "abdirectory://Pab2") || + !PL_strcmp(mURI, "abdirectory://Pab3")) + { + for (int j = 0; j < 2; j++) + { + nsAutoString currentCardStr; + if (!PL_strcmp(mURI, "abdirectory://Pab1")) + currentCardStr.Append("abcard://Pab1/Card"); + if (!PL_strcmp(mURI, "abdirectory://Pab2")) + currentCardStr.Append("abcard://Pab2/Card"); + if (!PL_strcmp(mURI, "abdirectory://Pab3")) + currentCardStr.Append("abcard://Pab3/Card"); + nsCOMPtr childCard; + if (j == 0) currentCardStr.Append('1'); + if (j == 1) currentCardStr.Append('2'); + AddChildCards(currentCardStr, getter_AddRefs(childCard)); + } + } + mCardInitialized = PR_TRUE; + } +// return mSubCards->Enumerate(result); + return mSubDirectories->Enumerate(result); +} + +nsresult nsABDirectory::AddChildCards(nsAutoString name, nsIAbCard **childCard) +{ + if(!childCard) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); + + if(NS_FAILED(rv)) + return rv; + + nsAutoString uri(name); + char* uriStr = uri.ToNewCString(); + if (uriStr == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + nsCOMPtr res; + rv = rdf->GetResource(uriStr, getter_AddRefs(res)); + if (NS_FAILED(rv)) + { + delete[] uriStr; + return rv; + } + nsCOMPtr personCard(do_QueryInterface(res, &rv)); + if (NS_FAILED(rv)) + { + rv = nsComponentManager::CreateInstance(kAbCardCID, nsnull, nsIAbCard::GetIID(), getter_AddRefs(personCard)); + if (NS_FAILED(rv) || !personCard) + { + delete[] uriStr; + return rv; + } + } + delete[] uriStr; + +// mSubCards->AppendElement(personCard); + mSubDirectories->AppendElement(personCard); + *childCard = personCard; + NS_ADDREF(*childCard); + + return rv; +} + + +NS_IMETHODIMP nsABDirectory::CreateCardFromDirectory(nsIAbCard* *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectory::AddAddrBookListener(nsIAbListener * listener) +{ + if (! mListeners) + { + mListeners = new nsVoidArray(); + if(!mListeners) + return NS_ERROR_OUT_OF_MEMORY; + } + mListeners->AppendElement(listener); + return NS_OK; +} + +NS_IMETHODIMP nsABDirectory::RemoveAddrBookListener(nsIAbListener * listener) +{ + if (! mListeners) + return NS_OK; + mListeners->RemoveElement(listener); + return NS_OK; + +} + + +//////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP_(PRUint32) nsABDirectory::Count(void) const +{ + PRUint32 count; + nsresult rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + return count; +} + +NS_IMETHODIMP nsABDirectory::AppendElement(nsISupports *aElement) +{ + return mSubDirectories->AppendElement(aElement); +} + +NS_IMETHODIMP nsABDirectory::RemoveElement(nsISupports *aElement) +{ + return mSubDirectories->RemoveElement(aElement); +} + + +NS_IMETHODIMP nsABDirectory::Enumerate(nsIEnumerator* *result) +{ + // nsABDirectory only have subfolders, no message elements + /* nsCOMPtr directories; + nsCOMPtr cards; + nsresult rv = GetChildNodes(getter_AddRefs(directories)); + if (NS_FAILED(rv)) return rv; + rv = GetChildCards(getter_AddRefs(cards)); + if (NS_FAILED(rv)) return rv; + return NS_NewConjoiningEnumerator(directories, cards, + (nsIBidirectionalEnumerator**)result);*/ + return mSubDirectories->Enumerate(result); +} + +NS_IMETHODIMP nsABDirectory::Clear(void) +{ + return mSubDirectories->Clear(); +} + +NS_IMETHODIMP nsABDirectory::GetName(char **name) +{ + if(!name) + return NS_ERROR_NULL_POINTER; + + if (!PL_strcmp(mURI, "abdirectory://Pab1")) + SetName("Address Book 1"); + if (!PL_strcmp(mURI, "abdirectory://Pab2")) + SetName("Address Book 2"); + if (!PL_strcmp(mURI, "abdirectory://Pab3")) + SetName("Address Book 3"); + if (!PL_strcmp(mURI, "abdirectory://Pab1/Card1")) + SetName("Person1"); + if (!PL_strcmp(mURI, "abdirectory://Pab1/Card2")) + SetName("Person2"); + if (!PL_strcmp(mURI, "abdirectory://Pab2/Card1")) + SetName("Person3"); + if (!PL_strcmp(mURI, "abdirectory://Pab2/Card2")) + SetName("Person4"); + if (!PL_strcmp(mURI, "abdirectory://Pab3/Card1")) + SetName("Person5"); + if (!PL_strcmp(mURI, "abdirectory://Pab3/Card2")) + SetName("Person6"); + *name = mDirName.ToNewCString(); + return NS_OK; +} + +NS_IMETHODIMP nsABDirectory::SetName(char * name) +{ + mDirName = name; + return NS_OK; +} + +NS_IMETHODIMP nsABDirectory::GetParent(nsIAbBase* *parent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectory::SetParent(nsIAbBase *parent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectory::GetChildNamed(const char* name, nsISupports* *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectory::ContainsChildNamed(const char *name, PRBool* containsChild) +{ + nsCOMPtr child; + + if(containsChild) + { + *containsChild = PR_FALSE; + if(NS_SUCCEEDED(GetChildNamed(name, getter_AddRefs(child)))) + { + *containsChild = child != nsnull; + } + return NS_OK; + } + else + return NS_ERROR_NULL_POINTER; +} + +NS_IMETHODIMP nsABDirectory::FindParentOf(nsIAbDirectory * aDirectory, nsIAbDirectory ** aParent) +{ + if(!aParent) + return NS_ERROR_NULL_POINTER; + + nsresult rv; + + *aParent = nsnull; + + PRUint32 count; + rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + nsCOMPtr supports; + nsCOMPtr child; + + for (PRUint32 i = 0; i < count && *aParent == NULL; i++) + { + supports = getter_AddRefs(mSubDirectories->ElementAt(i)); + child = do_QueryInterface(supports, &rv); + if(NS_SUCCEEDED(rv) && child) + { + if (aDirectory == child.get()) + { + *aParent = this; + NS_ADDREF(*aParent); + return NS_OK; + } + } + } + + for (PRUint32 j = 0; j < count && *aParent == NULL; j++) + { +/* + supports = getter_AddRefs(mSubDirectories->ElementAt(j)); + child = do_QueryInterface(supports, &rv); + if(NS_SUCCEEDED(rv) && child) + { + rv = child->FindParentOf(aDirectory, aParent); + if(NS_SUCCEEDED(rv)) + return rv; + } +*/ + } + + return rv; + +} + +NS_IMETHODIMP nsABDirectory::IsParentOf(nsIAbDirectory *child, PRBool deep, PRBool *isParent) +{ + if(!isParent) + return NS_ERROR_NULL_POINTER; + + nsresult rv = NS_OK; + + PRUint32 count; + rv = mSubDirectories->Count(&count); + NS_ASSERTION(NS_SUCCEEDED(rv), "Count failed"); + + for (PRUint32 i = 0; i < count; i++) + { + nsCOMPtr supports = getter_AddRefs(mSubDirectories->ElementAt(i)); + nsCOMPtr directory(do_QueryInterface(supports, &rv)); + if(NS_SUCCEEDED(rv)) + { + if (directory.get() == child ) + *isParent = PR_TRUE; + else if(deep) + {; +// directory->IsParentOf(child, deep, isParent); + } + } + if(*isParent) + return NS_OK; + } + *isParent = PR_FALSE; + return rv; +} + + +#ifdef HAVE_DB +NS_IMETHOD GetTotalPersonsInDB(PRUint32 *totalPersons) const; // How many messages in database. +#endif + diff --git a/mailnews/addrbook/src/nsAbDirectory.h b/mailnews/addrbook/src/nsAbDirectory.h new file mode 100644 index 000000000000..66d44b92146d --- /dev/null +++ b/mailnews/addrbook/src/nsAbDirectory.h @@ -0,0 +1,119 @@ +/* -*- 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 "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. + */ + +/******************************************************************************************************** + + Interface for representing Address Book Directory + +*********************************************************************************************************/ + +#ifndef nsABDirectory_h__ +#define nsABDirectory_h__ + +#include "msgCore.h" +#include "nsIAbDirectory.h" /* include the interface we are going to support */ +#include "nsRDFResource.h" +#include "nsIAbCard.h" +#include "nsISupportsArray.h" +#include "nsCOMPtr.h" + + /* + * Address Book Directory + */ + +class nsABDirectory: public nsRDFResource, public nsIAbDirectory +{ +public: + nsABDirectory(void); + virtual ~nsABDirectory(void); + + NS_DECL_ISUPPORTS_INHERITED + + // nsICollection methods: + NS_IMETHOD_(PRUint32) Count(void) const; + NS_IMETHOD AppendElement(nsISupports *aElement); + NS_IMETHOD RemoveElement(nsISupports *aElement); + NS_IMETHOD Enumerate(nsIEnumerator* *result); + NS_IMETHOD Clear(void); + + // nsIABBase methods: + NS_IMETHOD GetURI(char* *name) { return nsRDFResource::GetValue(name); } + NS_IMETHOD GetName(char **name); + NS_IMETHOD SetName(char *name); + NS_IMETHOD GetChildNamed(const char *name, nsISupports* *result); + NS_IMETHOD GetParent(nsIAbBase* *parent); + NS_IMETHOD SetParent(nsIAbBase *parent); + NS_IMETHOD GetChildNodes(nsIEnumerator* *result); + NS_IMETHOD AddAddrBookListener(nsIAbListener * listener); + NS_IMETHOD RemoveAddrBookListener(nsIAbListener * listener); + + + // nsIAbDirectory methods: + NS_IMETHOD AddUnique(nsISupports* element); + NS_IMETHOD ReplaceElement(nsISupports* element, nsISupports* newElement); + NS_IMETHOD GetChildCards(nsIEnumerator* *result); + NS_IMETHOD CreateCardFromDirectory(nsIAbCard* *result); +// NS_IMETHOD GetVisibleSubFolders(nsIEnumerator* *result); + +// NS_IMETHOD GetPrettyName(char ** name); +// NS_IMETHOD SetPrettyName(char * name); +// NS_IMETHOD BuildDirectoryURL(char ** url); + + +// NS_IMETHOD GetPrettiestName(char ** name); + +// NS_IMETHOD OnCloseDirectory(); +// NS_IMETHOD Delete(); + + NS_IMETHODIMP ContainsChildNamed(const char *name, PRBool* containsChild); + NS_IMETHODIMP FindParentOf(nsIAbDirectory * aDirectory, nsIAbDirectory ** aParent); + NS_IMETHODIMP IsParentOf(nsIAbDirectory *child, PRBool deep, PRBool *isParent); + +// NS_IMETHOD CreateSubDirectory(const char *dirName); + +// NS_IMETHOD Rename(const char *name); + +// NS_IMETHOD GetDepth(PRUint32 *depth); +// NS_IMETHOD SetDepth(PRUint32 depth); + +#ifdef HAVE_DB + NS_IMETHOD GetTotalPersonsInDB(PRUint32 *totalPersons) const; // How many messages in database. +#endif + +protected: +// nsresult NotifyPropertyChanged(char *property, char* oldValue, char* newValue); +// nsresult NotifyItemAdded(nsISupports *item); +// nsresult NotifyItemDeleted(nsISupports *item); + nsresult AddSubDirectory(nsAutoString name, nsIAbDirectory **childDir); + nsresult AddChildCards(nsAutoString name, nsIAbCard **childDir); + +protected: + nsString mDirName; + nsCOMPtr mSubDirectories; + nsCOMPtr mSubCards; + nsVoidArray *mListeners; + PRBool mInitialized; + PRBool mCardInitialized; + + PRInt16 mCsid; // default csid for folder/newsgroup - maintained by fe. + PRUint8 mDepth; + PRInt32 mPrefFlags; // prefs like MSG_PREF_OFFLINE, MSG_PREF_ONE_PANE, etc + +}; + +#endif diff --git a/mailnews/addrbook/src/nsCardDataSource.cpp b/mailnews/addrbook/src/nsCardDataSource.cpp new file mode 100644 index 000000000000..8af0251fd119 --- /dev/null +++ b/mailnews/addrbook/src/nsCardDataSource.cpp @@ -0,0 +1,707 @@ +/* -*- 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 "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) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "msgCore.h" // precompiled header... + +#include "nsCardDataSource.h" +#include "nsAbBaseCID.h" +#include "nsIAbCard.h" + +#include "nsIMsgDatabase.h" + +#include "rdf.h" +#include "nsIRDFService.h" +#include "nsRDFCID.h" +#include "nsIRDFNode.h" +#include "nsEnumeratorUtils.h" + +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsXPIDLString.h" + +// this is used for notification of observers using nsVoidArray +typedef struct _nsAbRDFNotification { + nsIRDFResource *subject; + nsIRDFResource *property; + nsIRDFNode *object; +} nsAbRDFNotification; + + + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); + +// we need this because of an egcs 1.0 (and possibly gcc) compiler bug +// that doesn't allow you to call ::nsISupports::GetIID() inside of a class +// that multiply inherits from nsISupports +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static NS_DEFINE_CID(kAbCardDataSourceCID, NS_ABCARDDATASOURCE_CID); + +nsIRDFResource* nsABCardDataSource::kNC_PersonName; +nsIRDFResource* nsABCardDataSource::kNC_ListName; +nsIRDFResource* nsABCardDataSource::kNC_Email; +nsIRDFResource* nsABCardDataSource::kNC_City; +nsIRDFResource* nsABCardDataSource::kNC_Organization; +nsIRDFResource* nsABCardDataSource::kNC_WorkPhone; +nsIRDFResource* nsABCardDataSource::kNC_Nickname; + +// commands +nsIRDFResource* nsABCardDataSource::kNC_Delete; +nsIRDFResource* nsABCardDataSource::kNC_NewCard; + +#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#" + +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, PersonName); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, ListName); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Email); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, City); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Organization); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, WorkPhone); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Nickname); + +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Delete); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, NewCard); + +//////////////////////////////////////////////////////////////////////// +// Utilities + +static PRBool +peq(nsIRDFResource* r1, nsIRDFResource* r2) +{ + PRBool result; + if (NS_SUCCEEDED(r1->EqualsResource(r2, &result)) && result) { + return PR_TRUE; + } else { + return PR_FALSE; + } +} + +static PRBool +peqSort(nsIRDFResource* r1, nsIRDFResource* r2, PRBool *isSort) +{ + if(!isSort) + return PR_FALSE; + + char *r1Str, *r2Str; + nsString r1nsStr, r2nsStr, r1nsSortStr; + + r1->GetValue(&r1Str); + r2->GetValue(&r2Str); + + r1nsStr = r1Str; + r2nsStr = r2Str; + r1nsSortStr = r1Str; + + delete[] r1Str; + delete[] r2Str; + + //probably need to not assume this will always come directly after property. + r1nsSortStr +="?sort=true"; + + if(r1nsStr == r2nsStr) + { + *isSort = PR_FALSE; + return PR_TRUE; + } + else if(r1nsSortStr == r2nsStr) + { + *isSort = PR_TRUE; + return PR_TRUE; + } + else + { + //In case the resources are equal but the values are different. I'm not sure if this + //could happen but it is feasible given interface. + *isSort = PR_FALSE; + return(peq(r1, r2)); + } +} + +void nsABCardDataSource::createNode(nsString& str, nsIRDFNode **node) +{ + *node = nsnull; + nsresult rv; + NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); + if (NS_FAILED(rv)) return; // always check this before proceeding + nsIRDFLiteral * value; + if(NS_SUCCEEDED(rdf->GetLiteral(str.GetUnicode(), &value))) { + *node = value; + } +} + +void nsABCardDataSource::createNode(PRUint32 value, nsIRDFNode **node) +{ + char *valueStr = PR_smprintf("%d", value); + nsString str(valueStr); + createNode(str, node); + PR_smprintf_free(valueStr); +} + +nsABCardDataSource::nsABCardDataSource(): + mURI(nsnull), + mObservers(nsnull), + mInitialized(PR_FALSE), + mRDFService(nsnull) +{ + NS_INIT_REFCNT(); + + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &mRDFService); // XXX probably need shutdown listener here + + PR_ASSERT(NS_SUCCEEDED(rv)); +} + +nsABCardDataSource::~nsABCardDataSource (void) +{ + mRDFService->UnregisterDataSource(this); + + PL_strfree(mURI); + if (mObservers) { + for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) { + nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i); + NS_RELEASE(obs); + } + delete mObservers; + } + nsrefcnt refcnt; + + NS_RELEASE2(kNC_PersonName, refcnt); + NS_RELEASE2(kNC_ListName, refcnt); + NS_RELEASE2(kNC_Email, refcnt); + NS_RELEASE2(kNC_City, refcnt); + NS_RELEASE2(kNC_Organization, refcnt); + NS_RELEASE2(kNC_WorkPhone, refcnt); + NS_RELEASE2(kNC_Nickname, refcnt); + + NS_RELEASE2(kNC_Delete, refcnt); + NS_RELEASE2(kNC_NewCard, refcnt); + + nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService); // XXX probably need shutdown listener here + mRDFService = nsnull; +} + + +NS_IMPL_ADDREF(nsABCardDataSource) +NS_IMPL_RELEASE(nsABCardDataSource) + +NS_IMETHODIMP +nsABCardDataSource::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = nsnull; + if (iid.Equals(nsIRDFDataSource::GetIID()) || + iid.Equals(kISupportsIID)) + { + *result = NS_STATIC_CAST(nsIRDFDataSource*, this); + AddRef(); + return NS_OK; + } + else if(iid.Equals(nsIAbListener::GetIID())) + { + *result = NS_STATIC_CAST(nsIAbListener*, this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + // nsIRDFDataSource methods +NS_IMETHODIMP nsABCardDataSource::Init(const char* uri) +{ + if (mInitialized) + return NS_ERROR_ALREADY_INITIALIZED; + + if ((mURI = PL_strdup(uri)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + mRDFService->RegisterDataSource(this, PR_FALSE); + + if (! kNC_PersonName) { + + mRDFService->GetResource(kURINC_PersonName, &kNC_PersonName); + mRDFService->GetResource(kURINC_ListName, &kNC_ListName); + mRDFService->GetResource(kURINC_Email, &kNC_Email); + mRDFService->GetResource(kURINC_City, &kNC_City); + mRDFService->GetResource(kURINC_Organization, &kNC_Organization); + mRDFService->GetResource(kURINC_WorkPhone, &kNC_WorkPhone); + mRDFService->GetResource(kURINC_Nickname, &kNC_Nickname); + + mRDFService->GetResource(kURINC_Delete, &kNC_Delete); + mRDFService->GetResource(kURINC_NewCard, &kNC_NewCard); + } + mInitialized = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::GetURI(char* *uri) +{ + if ((*uri = nsXPIDLCString::Copy(mURI)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + else + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCardDataSource::GetTarget(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsIRDFNode** target) +{ + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the mail data source. + if (! tv) + return NS_RDF_NO_VALUE; + + nsCOMPtr card(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv) && card) { + rv = createCardNode(card, property, target); + } + else + return NS_RDF_NO_VALUE; + return rv; +} + + +NS_IMETHODIMP nsABCardDataSource::GetSources(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsISimpleEnumerator** sources) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCardDataSource::GetTargets(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsISimpleEnumerator** targets) +{ + nsresult rv = NS_RDF_NO_VALUE; + + nsCOMPtr card(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv) && card) + { + if(peq(kNC_PersonName, property) || peq(kNC_ListName, property) || + peq(kNC_Email, property) || peq(kNC_City, property) || + peq(kNC_Organization, property) || peq(kNC_WorkPhone, property) || + peq(kNC_Nickname, property)) + { + nsSingletonEnumerator* cursor = + new nsSingletonEnumerator(property); + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + } + else { + //create empty cursor + nsCOMPtr assertions; + NS_NewISupportsArray(getter_AddRefs(assertions)); + nsArrayEnumerator* cursor = + new nsArrayEnumerator(assertions); + if(cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + + return rv; +} + +NS_IMETHODIMP nsABCardDataSource::Assert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCardDataSource::Unassert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP nsABCardDataSource::HasAssertion(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + PRBool* hasAssertion) +{ + *hasAssertion = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::AddObserver(nsIRDFObserver* n) +{ + if (! mObservers) { + if ((mObservers = new nsVoidArray()) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + } + mObservers->AppendElement(n); + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::RemoveObserver(nsIRDFObserver* n) +{ + if (! mObservers) + return NS_OK; + mObservers->RemoveElement(n); + return NS_OK; +} + +PRBool +nsABCardDataSource::assertEnumFunc(void *aElement, void *aData) +{ + nsAbRDFNotification *note = (nsAbRDFNotification *)aData; + nsIRDFObserver* observer = (nsIRDFObserver *)aElement; + + observer->OnAssert(note->subject, + note->property, + note->object); + return PR_TRUE; +} + +PRBool +nsABCardDataSource::unassertEnumFunc(void *aElement, void *aData) +{ + nsAbRDFNotification* note = (nsAbRDFNotification *)aData; + nsIRDFObserver* observer = (nsIRDFObserver *)aElement; + + observer->OnUnassert(note->subject, + note->property, + note->object); + return PR_TRUE; +} + +nsresult nsABCardDataSource::NotifyObservers(nsIRDFResource *subject, + nsIRDFResource *property, + nsIRDFNode *object, + PRBool assert) +{ + if(mObservers) + { + nsAbRDFNotification note = { subject, property, object }; + if (assert) + mObservers->EnumerateForwards(assertEnumFunc, ¬e); + else + mObservers->EnumerateForwards(unassertEnumFunc, ¬e); + } + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::ArcLabelsIn(nsIRDFNode* node, + nsISimpleEnumerator** labels) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCardDataSource::ArcLabelsOut(nsIRDFResource* source, + nsISimpleEnumerator** labels) +{ + nsCOMPtr arcs; + nsresult rv = NS_RDF_NO_VALUE; + + nsCOMPtr card(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv) && card) { + fflush(stdout); + rv = getCardArcLabelsOut(card, getter_AddRefs(arcs)); + } + else { + // how to return an empty cursor? + // for now return a 0-length nsISupportsArray + NS_NewISupportsArray(getter_AddRefs(arcs)); + } + + nsArrayEnumerator* cursor = + new nsArrayEnumerator(arcs); + + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *labels = cursor; + return NS_OK; +} + +nsresult +nsABCardDataSource::getCardArcLabelsOut(nsIAbCard *card, + nsISupportsArray **arcs) +{ + nsresult rv; + rv = NS_NewISupportsArray(arcs); + if(NS_FAILED(rv)) + return rv; + + nsCOMPtr cards; + if(NS_SUCCEEDED(card->GetChildNodes(getter_AddRefs(cards)))) + { + if(NS_OK == cards->First()) + { + nsCOMPtr firstCard; + rv = cards->CurrentItem(getter_AddRefs(firstCard)); + if (NS_SUCCEEDED(rv)) + { + (*arcs)->AppendElement(kNC_PersonName); + (*arcs)->AppendElement(kNC_ListName); + (*arcs)->AppendElement(kNC_Email); + (*arcs)->AppendElement(kNC_City); + (*arcs)->AppendElement(kNC_Organization); + (*arcs)->AppendElement(kNC_WorkPhone); + (*arcs)->AppendElement(kNC_Nickname); + + } + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsABCardDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + NS_NOTYETIMPLEMENTED("sorry!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABCardDataSource::Flush() +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsABCardDataSource::GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands) +{ + nsresult rv; + nsCOMPtr cmds; + + nsCOMPtr card(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv)) { + rv = NS_NewISupportsArray(getter_AddRefs(cmds)); + if (NS_FAILED(rv)) return rv; + cmds->AppendElement(kNC_Delete); + cmds->AppendElement(kNC_NewCard); + } + + if (cmds != nsnull) + return cmds->Enumerate(commands); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsABCardDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + nsresult rv; + nsCOMPtr card; + + PRUint32 cnt; + rv = aSources->Count(&cnt); + for (PRUint32 i = 0; i < cnt; i++) { + nsCOMPtr source = getter_AddRefs((*aSources)[i]); + card = do_QueryInterface(source, &rv); + if (NS_SUCCEEDED(rv)) { + // we don't care about the arguments -- card commands are always enabled + if (!(peq(aCommand, kNC_Delete) || + peq(aCommand, kNC_NewCard))) { + *aResult = PR_FALSE; + return NS_OK; + } + } + } + *aResult = PR_TRUE; + return NS_OK; // succeeded for all sources +} + +NS_IMETHODIMP +nsABCardDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + nsresult rv = NS_OK; + + // XXX need to handle batching of command applied to all sources + + PRUint32 cnt; + rv = aSources->Count(&cnt); + for (PRUint32 i = 0; i < cnt; i++) { + nsCOMPtr supports = getter_AddRefs((*aSources)[i]); + nsCOMPtr card = do_QueryInterface(supports, &rv); + if (NS_SUCCEEDED(rv)) { + if (peq(aCommand, kNC_Delete)) { + rv = DoDeleteFromCard(card, aArguments); + } + else if(peq(aCommand, kNC_NewCard)) { + rv = DoNewCard(card, aArguments); + } + + } + } + return rv; +} + +NS_IMETHODIMP nsABCardDataSource::OnItemAdded(nsIAbBase *parentDirectory, nsISupports *item) +{ +/* nsresult rv; + nsCOMPtr card; + nsCOMPtr parentResource; + + if(NS_SUCCEEDED(parentDirectory->QueryInterface(nsIRDFResource::GetIID(), getter_AddRefs(parentResource)))) + { + //If we are adding a card + if(NS_SUCCEEDED(item->QueryInterface(nsIAbCard::GetIID(), getter_AddRefs(card)))) + { + nsCOMPtr itemNode(do_QueryInterface(item, &rv)); + if(NS_SUCCEEDED(rv)) + { + //Notify directories that a message was added. + NotifyObservers(parentResource, kNC_CardChild, itemNode, PR_TRUE); + } + } + }*/ + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::OnItemRemoved(nsIAbBase *parentDirectory, nsISupports *item) +{ +/* + nsresult rv; + nsCOMPtr card; + nsCOMPtr parentResource; + + if(NS_SUCCEEDED(parentDirectory->QueryInterface(nsIRDFResource::GetIID(), getter_AddRefs(parentResource)))) + { + //If we are adding a card + if(NS_SUCCEEDED(item->QueryInterface(nsIAbCard::GetIID(), getter_AddRefs(card)))) + { + nsCOMPtr itemNode(do_QueryInterface(item, &rv)); + if(NS_SUCCEEDED(rv)) + { + //Notify directories that a card was deleted. + NotifyObservers(parentResource, kNC_CardChild, itemNode, PR_FALSE); + } + } + }*/ + return NS_OK; +} + +NS_IMETHODIMP nsABCardDataSource::OnItemPropertyChanged(nsISupports *item, const char *property, + const char *oldValue, const char *newValue) + +{ + /* + nsresult rv; + nsCOMPtr resource(do_QueryInterface(item, &rv)); + + if(NS_SUCCEEDED(rv)) + { + if(PL_strcmp("PersonName", property) == 0) + { + NotifyPropertyChanged(resource, kNC_DirName, oldValue, newValue); + } + }*/ + + + return NS_OK; +} + +nsresult nsABCardDataSource::NotifyPropertyChanged(nsIRDFResource *resource, + nsIRDFResource *propertyResource, + const char *oldValue, const char *newValue) +{ + nsCOMPtr oldValueNode; + nsCOMPtr newValueNode; + nsString oldValueStr = oldValue; + nsString newValueStr = newValue; + createNode(oldValueStr, getter_AddRefs(oldValueNode)); + createNode(newValueStr, getter_AddRefs(newValueNode)); + NotifyObservers(resource, propertyResource, oldValueNode, PR_FALSE); + NotifyObservers(resource, propertyResource, newValueNode, PR_TRUE); + return NS_OK; +} + +nsresult nsABCardDataSource::createCardNode(nsIAbCard* card, + nsIRDFResource* property, + nsIRDFNode** target) +{ + char *name; + nsresult rv = NS_RDF_NO_VALUE; + + if (peq(kNC_PersonName, property)) + rv = card->GetPersonName(&name); + else if (peq(kNC_ListName, property)) + rv = card->GetListName(&name); + else if (peq(kNC_Email, property)) + rv = card->GetEmail(&name); + else if (peq(kNC_City, property)) + rv = card->GetCity(&name); + else if (peq(kNC_Organization, property)) + rv = card->GetOrganization(&name); + else if (peq(kNC_WorkPhone, property)) + rv = card->GetWorkPhone(&name); + else if (peq(kNC_Nickname, property)) + rv = card->GetNickname(&name); + if (NS_FAILED(rv)) return rv; + nsString nameString(name); + createNode(nameString, target); + delete[] name; + return NS_OK; +} + +nsresult nsABCardDataSource::DoDeleteFromCard(nsIAbCard *card, nsISupportsArray *arguments) +{ + nsresult rv = NS_OK; + return rv; +} + +nsresult nsABCardDataSource::DoNewCard(nsIAbCard *card, nsISupportsArray *arguments) +{ + nsresult rv = NS_OK; + nsCOMPtr literal(do_QueryInterface((*arguments)[0], &rv)); + if(NS_SUCCEEDED(rv)) + { + PRUnichar *name; + literal->GetValue(&name); + nsString tempStr = name; + nsAutoCString nameStr(tempStr); + +// rv = card->CreateNewCard(nameStr); + } + return rv; +} diff --git a/mailnews/addrbook/src/nsCardDataSource.h b/mailnews/addrbook/src/nsCardDataSource.h new file mode 100644 index 000000000000..094908bf5e43 --- /dev/null +++ b/mailnews/addrbook/src/nsCardDataSource.h @@ -0,0 +1,157 @@ +/* -*- 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 "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) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIRDFDataSource.h" +#include "nsIRDFService.h" +#include "nsIAbListener.h" +#include "nsIAbCard.h" + + +/** + * The addressbook person card data source. + */ +class nsABCardDataSource : public nsIRDFDataSource, + public nsIAbListener +{ +private: + char* mURI; + nsVoidArray* mObservers; + PRBool mInitialized; + + // The cached service managers + + nsIRDFService* mRDFService; + +public: + + NS_DECL_ISUPPORTS + + nsABCardDataSource(void); + virtual ~nsABCardDataSource (void); + + + // nsIRDFDataSource methods + NS_IMETHOD Init(const char* uri); + + NS_IMETHOD GetURI(char* *uri); + + NS_IMETHOD GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */); + + NS_IMETHOD GetTarget(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsIRDFNode** target); + + NS_IMETHOD GetSources(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsISimpleEnumerator** sources); + + NS_IMETHOD GetTargets(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsISimpleEnumerator** targets); + + NS_IMETHOD Assert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv); + + NS_IMETHOD Unassert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target); + + NS_IMETHOD HasAssertion(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + PRBool* hasAssertion); + + NS_IMETHOD AddObserver(nsIRDFObserver* n); + + NS_IMETHOD RemoveObserver(nsIRDFObserver* n); + + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, + nsISimpleEnumerator** labels); + + NS_IMETHOD ArcLabelsOut(nsIRDFResource* source, + nsISimpleEnumerator** labels); + + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aCursor); + + NS_IMETHOD Flush(); + + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); + + NS_IMETHOD OnItemAdded(nsIAbBase *parentDirectory, nsISupports *item); + + NS_IMETHOD OnItemRemoved(nsIAbBase *parentDirectory, nsISupports *item); + + NS_IMETHOD OnItemPropertyChanged(nsISupports *item, const char *property, + const char *oldValue, const char *newValue); + + // caching frequently used resources +protected: + + void createNode(nsString& str, nsIRDFNode **node); + void createNode(PRUint32 value, nsIRDFNode **node); + nsresult NotifyPropertyChanged(nsIRDFResource *resource, nsIRDFResource *propertyResource, + const char *oldValue, const char *newValue); + + nsresult NotifyObservers(nsIRDFResource *subject, nsIRDFResource *property, + nsIRDFNode *object, PRBool assert); + nsresult createCardNode(nsIAbCard* directory, nsIRDFResource* property, + nsIRDFNode** target); + static nsresult getCardArcLabelsOut(nsIAbCard *directory, + nsISupportsArray **arcs); + + nsresult DoDeleteFromCard(nsIAbCard *directory, + nsISupportsArray *arguments); + + nsresult DoNewCard(nsIAbCard *directory, + nsISupportsArray *arguments); + + static PRBool assertEnumFunc(void *aElement, void *aData); + static PRBool unassertEnumFunc(void *aElement, void *aData); + + static nsIRDFResource* kNC_PersonName; + static nsIRDFResource* kNC_ListName; + static nsIRDFResource* kNC_Email; + static nsIRDFResource* kNC_City; + static nsIRDFResource* kNC_Organization; + static nsIRDFResource* kNC_WorkPhone; + static nsIRDFResource* kNC_Nickname; + + // commands + static nsIRDFResource* kNC_Delete; + static nsIRDFResource* kNC_NewCard; + +}; diff --git a/mailnews/addrbook/src/nsDirectoryDataSource.cpp b/mailnews/addrbook/src/nsDirectoryDataSource.cpp new file mode 100644 index 000000000000..57aff3034844 --- /dev/null +++ b/mailnews/addrbook/src/nsDirectoryDataSource.cpp @@ -0,0 +1,753 @@ +/* -*- 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 "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) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "msgCore.h" // precompiled header... + +#include "nsDirectoryDataSource.h" +#include "nsAbBaseCID.h" +#include "nsAbdirectory.h" + +#include "nsIMsgDatabase.h" + +#include "rdf.h" +#include "nsIRDFService.h" +#include "nsRDFCID.h" +#include "nsIRDFNode.h" +#include "nsEnumeratorUtils.h" + +#include "nsString.h" +#include "nsCOMPtr.h" +#include "nsXPIDLString.h" + +// this is used for notification of observers using nsVoidArray +typedef struct _nsAbRDFNotification { + nsIRDFResource *subject; + nsIRDFResource *property; + nsIRDFNode *object; +} nsAbRDFNotification; + + + +static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); + +// we need this because of an egcs 1.0 (and possibly gcc) compiler bug +// that doesn't allow you to call ::nsISupports::GetIID() inside of a class +// that multiply inherits from nsISupports +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +static NS_DEFINE_CID(kAbDirectoryDataSourceCID, NS_ABDIRECTORYDATASOURCE_CID); + +nsIRDFResource* nsABDirectoryDataSource::kNC_Child; +nsIRDFResource* nsABDirectoryDataSource::kNC_DirName; +nsIRDFResource* nsABDirectoryDataSource::kNC_DirChild; +nsIRDFResource* nsABDirectoryDataSource::kNC_CardChild; + +// commands +nsIRDFResource* nsABDirectoryDataSource::kNC_Delete; +nsIRDFResource* nsABDirectoryDataSource::kNC_NewDirectory; + +#define NC_NAMESPACE_URI "http://home.netscape.com/NC-rdf#" +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, child); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, DirName); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, DirChild); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, CardChild); + +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, Delete); +DEFINE_RDF_VOCAB(NC_NAMESPACE_URI, NC, NewDirectory); + +//////////////////////////////////////////////////////////////////////// +// Utilities + +static PRBool +peq(nsIRDFResource* r1, nsIRDFResource* r2) +{ + PRBool result; + if (NS_SUCCEEDED(r1->EqualsResource(r2, &result)) && result) { + return PR_TRUE; + } else { + return PR_FALSE; + } +} + +static PRBool +peqSort(nsIRDFResource* r1, nsIRDFResource* r2, PRBool *isSort) +{ + if(!isSort) + return PR_FALSE; + + char *r1Str, *r2Str; + nsString r1nsStr, r2nsStr, r1nsSortStr; + + r1->GetValue(&r1Str); + r2->GetValue(&r2Str); + + r1nsStr = r1Str; + r2nsStr = r2Str; + r1nsSortStr = r1Str; + + delete[] r1Str; + delete[] r2Str; + + //probably need to not assume this will always come directly after property. + r1nsSortStr +="?sort=true"; + + if(r1nsStr == r2nsStr) + { + *isSort = PR_FALSE; + return PR_TRUE; + } + else if(r1nsSortStr == r2nsStr) + { + *isSort = PR_TRUE; + return PR_TRUE; + } + else + { + //In case the resources are equal but the values are different. I'm not sure if this + //could happen but it is feasible given interface. + *isSort = PR_FALSE; + return(peq(r1, r2)); + } +} + +void nsABDirectoryDataSource::createNode(nsString& str, nsIRDFNode **node) +{ + *node = nsnull; + nsresult rv; + NS_WITH_SERVICE(nsIRDFService, rdf, kRDFServiceCID, &rv); + if (NS_FAILED(rv)) return; // always check this before proceeding + nsIRDFLiteral * value; + if(NS_SUCCEEDED(rdf->GetLiteral(str.GetUnicode(), &value))) { + *node = value; + } +} + +void nsABDirectoryDataSource::createNode(PRUint32 value, nsIRDFNode **node) +{ + char *valueStr = PR_smprintf("%d", value); + nsString str(valueStr); + createNode(str, node); + PR_smprintf_free(valueStr); +} + +nsABDirectoryDataSource::nsABDirectoryDataSource(): + mURI(nsnull), + mObservers(nsnull), + mInitialized(PR_FALSE), + mRDFService(nsnull) +{ + NS_INIT_REFCNT(); + + nsresult rv = nsServiceManager::GetService(kRDFServiceCID, + nsIRDFService::GetIID(), + (nsISupports**) &mRDFService); // XXX probably need shutdown listener here + + PR_ASSERT(NS_SUCCEEDED(rv)); +} + +nsABDirectoryDataSource::~nsABDirectoryDataSource (void) +{ + mRDFService->UnregisterDataSource(this); + + PL_strfree(mURI); + if (mObservers) { + for (PRInt32 i = mObservers->Count() - 1; i >= 0; --i) { + nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i); + NS_RELEASE(obs); + } + delete mObservers; + } + nsrefcnt refcnt; + NS_RELEASE2(kNC_Child, refcnt); + NS_RELEASE2(kNC_DirName, refcnt); + NS_RELEASE2(kNC_DirChild, refcnt); + NS_RELEASE2(kNC_CardChild, refcnt); + + NS_RELEASE2(kNC_Delete, refcnt); + NS_RELEASE2(kNC_NewDirectory, refcnt); + + nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService); // XXX probably need shutdown listener here + mRDFService = nsnull; +} + + +NS_IMPL_ADDREF(nsABDirectoryDataSource) +NS_IMPL_RELEASE(nsABDirectoryDataSource) + +NS_IMETHODIMP +nsABDirectoryDataSource::QueryInterface(REFNSIID iid, void** result) +{ + if (! result) + return NS_ERROR_NULL_POINTER; + + *result = nsnull; + if (iid.Equals(nsIRDFDataSource::GetIID()) || + iid.Equals(kISupportsIID)) + { + *result = NS_STATIC_CAST(nsIRDFDataSource*, this); + AddRef(); + return NS_OK; + } + else if(iid.Equals(nsIAbListener::GetIID())) + { + *result = NS_STATIC_CAST(nsIAbListener*, this); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + // nsIRDFDataSource methods +NS_IMETHODIMP nsABDirectoryDataSource::Init(const char* uri) +{ + if (mInitialized) + return NS_ERROR_ALREADY_INITIALIZED; + + if ((mURI = PL_strdup(uri)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + + mRDFService->RegisterDataSource(this, PR_FALSE); + + if (!kNC_Child) + mRDFService->GetResource(kURINC_child, &kNC_Child); + if (!kNC_DirName) + mRDFService->GetResource(kURINC_DirName, &kNC_DirName); + if (!kNC_DirChild) + mRDFService->GetResource(kURINC_DirChild, &kNC_DirChild); + if (!kNC_CardChild) + mRDFService->GetResource(kURINC_CardChild, &kNC_CardChild); + + if (!kNC_Delete) + mRDFService->GetResource(kURINC_Delete, &kNC_Delete); + if (!kNC_NewDirectory) + mRDFService->GetResource(kURINC_NewDirectory, &kNC_NewDirectory); + + mInitialized = PR_TRUE; + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::GetURI(char* *uri) +{ + if ((*uri = nsXPIDLCString::Copy(mURI)) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + else + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectoryDataSource::GetTarget(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsIRDFNode** target) +{ + nsresult rv = NS_RDF_NO_VALUE; + + // we only have positive assertions in the mail data source. + if (! tv) + return NS_RDF_NO_VALUE; + + nsCOMPtr directory(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv) && directory) { + rv = createDirectoryNode(directory, property, target); + } + else + return NS_RDF_NO_VALUE; + return rv; +} + + +NS_IMETHODIMP nsABDirectoryDataSource::GetSources(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsISimpleEnumerator** sources) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectoryDataSource::GetTargets(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsISimpleEnumerator** targets) +{ + nsresult rv = NS_RDF_NO_VALUE; + + nsCOMPtr directory(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv) && directory) + { + if (peq(kNC_Child, property)) + { + nsCOMPtr subDirectories; + + rv = directory->GetChildNodes(getter_AddRefs(subDirectories)); + if (NS_FAILED(rv)) return rv; + nsAdapterEnumerator* cursor = + new nsAdapterEnumerator(subDirectories); + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + else if(peq(kNC_DirName, property)) + { + nsSingletonEnumerator* cursor = + new nsSingletonEnumerator(property); + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + else if(peq(kNC_CardChild, property)) + { + nsCOMPtr cardChild; + + rv = directory->GetChildCards(getter_AddRefs(cardChild)); + if (NS_FAILED(rv)) return rv; + nsAdapterEnumerator* cursor = + new nsAdapterEnumerator(cardChild); + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + else if(peq(kNC_DirChild, property)) + { + rv = NS_OK; + } + } + else { + //create empty cursor + nsCOMPtr assertions; + NS_NewISupportsArray(getter_AddRefs(assertions)); + nsArrayEnumerator* cursor = + new nsArrayEnumerator(assertions); + if(cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *targets = cursor; + rv = NS_OK; + } + + return rv; +} + +NS_IMETHODIMP nsABDirectoryDataSource::Assert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectoryDataSource::Unassert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP nsABDirectoryDataSource::HasAssertion(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + PRBool* hasAssertion) +{ + *hasAssertion = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::AddObserver(nsIRDFObserver* n) +{ + if (! mObservers) { + if ((mObservers = new nsVoidArray()) == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + } + mObservers->AppendElement(n); + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::RemoveObserver(nsIRDFObserver* n) +{ + if (! mObservers) + return NS_OK; + mObservers->RemoveElement(n); + return NS_OK; +} + +PRBool +nsABDirectoryDataSource::assertEnumFunc(void *aElement, void *aData) +{ + nsAbRDFNotification *note = (nsAbRDFNotification *)aData; + nsIRDFObserver* observer = (nsIRDFObserver *)aElement; + + observer->OnAssert(note->subject, + note->property, + note->object); + return PR_TRUE; +} + +PRBool +nsABDirectoryDataSource::unassertEnumFunc(void *aElement, void *aData) +{ + nsAbRDFNotification* note = (nsAbRDFNotification *)aData; + nsIRDFObserver* observer = (nsIRDFObserver *)aElement; + + observer->OnUnassert(note->subject, + note->property, + note->object); + return PR_TRUE; +} + +nsresult nsABDirectoryDataSource::NotifyObservers(nsIRDFResource *subject, + nsIRDFResource *property, + nsIRDFNode *object, + PRBool assert) +{ + if(mObservers) + { + nsAbRDFNotification note = { subject, property, object }; + if (assert) + mObservers->EnumerateForwards(assertEnumFunc, ¬e); + else + mObservers->EnumerateForwards(unassertEnumFunc, ¬e); + } + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::ArcLabelsIn(nsIRDFNode* node, + nsISimpleEnumerator** labels) +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectoryDataSource::ArcLabelsOut(nsIRDFResource* source, + nsISimpleEnumerator** labels) +{ + nsCOMPtr arcs; + nsresult rv = NS_RDF_NO_VALUE; + + nsCOMPtr directory(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv)) { + fflush(stdout); + rv = getDirectoryArcLabelsOut(directory, getter_AddRefs(arcs)); + } + else { + // how to return an empty cursor? + // for now return a 0-length nsISupportsArray + NS_NewISupportsArray(getter_AddRefs(arcs)); + } + + nsArrayEnumerator* cursor = + new nsArrayEnumerator(arcs); + + if (cursor == nsnull) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(cursor); + *labels = cursor; + + return NS_OK; +} + +nsresult +nsABDirectoryDataSource::getDirectoryArcLabelsOut(nsIAbDirectory *directory, + nsISupportsArray **arcs) +{ + nsresult rv; + rv = NS_NewISupportsArray(arcs); + if(NS_FAILED(rv)) + return rv; + + (*arcs)->AppendElement(kNC_DirName); + + nsCOMPtr subDirectory; + if (NS_SUCCEEDED(directory->GetChildNodes(getter_AddRefs(subDirectory)))) + { + if(NS_OK == subDirectory->First()) + { + nsCOMPtr firstDir; + rv = subDirectory->CurrentItem(getter_AddRefs(firstDir)); + if (NS_SUCCEEDED(rv)) + (*arcs)->AppendElement(kNC_Child); + } + } + + nsCOMPtr cards; + if(NS_SUCCEEDED(directory->GetChildCards(getter_AddRefs(cards)))) + { + if(NS_OK == cards->First()) + { + nsCOMPtr firstCard; + rv = cards->CurrentItem(getter_AddRefs(firstCard)); + if (NS_SUCCEEDED(rv)) + (*arcs)->AppendElement(kNC_CardChild); + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsABDirectoryDataSource::GetAllResources(nsISimpleEnumerator** aCursor) +{ + NS_NOTYETIMPLEMENTED("sorry!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsABDirectoryDataSource::Flush() +{ + PR_ASSERT(0); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsABDirectoryDataSource::GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands) +{ + nsresult rv; + nsCOMPtr cmds; + + nsCOMPtr directory(do_QueryInterface(source, &rv)); + if (NS_SUCCEEDED(rv)) { + rv = NS_NewISupportsArray(getter_AddRefs(cmds)); + if (NS_FAILED(rv)) return rv; + cmds->AppendElement(kNC_Delete); + cmds->AppendElement(kNC_NewDirectory); + } + + if (cmds != nsnull) + return cmds->Enumerate(commands); + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP +nsABDirectoryDataSource::IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult) +{ + nsresult rv; + nsCOMPtr directory; + + PRUint32 cnt; + rv = aSources->Count(&cnt); + for (PRUint32 i = 0; i < cnt; i++) { + nsCOMPtr source = getter_AddRefs((*aSources)[i]); + directory = do_QueryInterface(source, &rv); + if (NS_SUCCEEDED(rv)) { + // we don't care about the arguments -- directory commands are always enabled + if (!(peq(aCommand, kNC_Delete) || + peq(aCommand, kNC_NewDirectory))) { + *aResult = PR_FALSE; + return NS_OK; + } + } + } + *aResult = PR_TRUE; + return NS_OK; // succeeded for all sources +} + +NS_IMETHODIMP +nsABDirectoryDataSource::DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments) +{ + nsresult rv = NS_OK; + + // XXX need to handle batching of command applied to all sources + + PRUint32 cnt; + rv = aSources->Count(&cnt); + for (PRUint32 i = 0; i < cnt; i++) { + nsCOMPtr supports = getter_AddRefs((*aSources)[i]); + nsCOMPtr directory = do_QueryInterface(supports, &rv); + if (NS_SUCCEEDED(rv)) { + if (peq(aCommand, kNC_Delete)) { + rv = DoDeleteFromDirectory(directory, aArguments); + } + else if(peq(aCommand, kNC_NewDirectory)) { + rv = DoNewDirectory(directory, aArguments); + } + + } + } + return rv; +} + +NS_IMETHODIMP nsABDirectoryDataSource::OnItemAdded(nsIAbBase *parentDirectory, nsISupports *item) +{ + nsresult rv; + nsCOMPtr directory; + nsCOMPtr parentResource; + + if(NS_SUCCEEDED(parentDirectory->QueryInterface(nsIRDFResource::GetIID(), getter_AddRefs(parentResource)))) + { + //If we are adding a directory + if(NS_SUCCEEDED(item->QueryInterface(nsIAbDirectory::GetIID(), getter_AddRefs(directory)))) + { + nsCOMPtr itemNode(do_QueryInterface(item, &rv)); + if(NS_SUCCEEDED(rv)) + { + //Notify directories that a message was added. + NotifyObservers(parentResource, kNC_Child, itemNode, PR_TRUE); + } + } + } + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::OnItemRemoved(nsIAbBase *parentDirectory, nsISupports *item) +{ +/* + nsresult rv; + nsCOMPtr card; + nsCOMPtr parentResource; + + if(NS_SUCCEEDED(parentDirectory->QueryInterface(nsIRDFResource::GetIID(), getter_AddRefs(parentResource)))) + { + //If we are adding a card + if(NS_SUCCEEDED(item->QueryInterface(nsIAbCard::GetIID(), getter_AddRefs(card)))) + { + nsCOMPtr itemNode(do_QueryInterface(item, &rv)); + if(NS_SUCCEEDED(rv)) + { + //Notify directories that a card was deleted. + NotifyObservers(parentResource, kNC_CardChild, itemNode, PR_FALSE); + } + } + }*/ + return NS_OK; +} + +NS_IMETHODIMP nsABDirectoryDataSource::OnItemPropertyChanged(nsISupports *item, const char *property, + const char *oldValue, const char *newValue) + +{ + /* + nsresult rv; + nsCOMPtr resource(do_QueryInterface(item, &rv)); + + if(NS_SUCCEEDED(rv)) + { + if(PL_strcmp("DirName", property) == 0) + { + NotifyPropertyChanged(resource, kNC_DirName, oldValue, newValue); + } + }*/ + + return NS_OK; +} + +nsresult nsABDirectoryDataSource::NotifyPropertyChanged(nsIRDFResource *resource, + nsIRDFResource *propertyResource, + const char *oldValue, const char *newValue) +{ + nsCOMPtr oldValueNode; + nsCOMPtr newValueNode; + nsString oldValueStr = oldValue; + nsString newValueStr = newValue; + createNode(oldValueStr, getter_AddRefs(oldValueNode)); + createNode(newValueStr, getter_AddRefs(newValueNode)); + NotifyObservers(resource, propertyResource, oldValueNode, PR_FALSE); + NotifyObservers(resource, propertyResource, newValueNode, PR_TRUE); + return NS_OK; +} + +nsresult nsABDirectoryDataSource::createDirectoryNode(nsIAbDirectory* directory, + nsIRDFResource* property, + nsIRDFNode** target) +{ + nsresult rv = NS_RDF_NO_VALUE; + + if (peq(kNC_DirName, property)) + rv = createDirectoryNameNode(directory, target); + else if (peq(kNC_Child, property)) + rv = createDirectoryChildNode(directory,target); + else if (peq(kNC_CardChild, property)) + rv = createCardChildNode(directory,target); + + return rv; +} + + +nsresult nsABDirectoryDataSource::createDirectoryNameNode(nsIAbDirectory *directory, + nsIRDFNode **target) +{ + char *name; + nsresult rv = directory->GetName(&name); + if (NS_FAILED(rv)) return rv; + nsString nameString(name); + createNode(nameString, target); + delete[] name; + return NS_OK; +} + +nsresult +nsABDirectoryDataSource::createDirectoryChildNode(nsIAbDirectory *directory, + nsIRDFNode **target) +{ + nsresult rv = NS_RDF_NO_VALUE; + + return NS_FAILED(rv) ? NS_RDF_NO_VALUE : rv; +} + +nsresult +nsABDirectoryDataSource::createCardChildNode(nsIAbDirectory *directory, + nsIRDFNode **target) +{ + char *name; + nsresult rv = directory->GetName(&name); + if (NS_FAILED(rv)) return rv; + nsString nameString(name); + createNode(nameString, target); + delete[] name; + return NS_OK; +} + +nsresult nsABDirectoryDataSource::DoDeleteFromDirectory(nsIAbDirectory *directory, nsISupportsArray *arguments) +{ + nsresult rv = NS_OK; + return rv; +} + +nsresult nsABDirectoryDataSource::DoNewDirectory(nsIAbDirectory *directory, nsISupportsArray *arguments) +{ + nsresult rv = NS_OK; + nsCOMPtr literal(do_QueryInterface((*arguments)[0], &rv)); + if(NS_SUCCEEDED(rv)) + { + PRUnichar *name; + literal->GetValue(&name); + nsString tempStr = name; + nsAutoCString nameStr(tempStr); + +// rv = directory->CreateSubDirectory(nameStr); + } + return rv; +} diff --git a/mailnews/addrbook/src/nsDirectoryDataSource.h b/mailnews/addrbook/src/nsDirectoryDataSource.h new file mode 100644 index 000000000000..d790f14b07e9 --- /dev/null +++ b/mailnews/addrbook/src/nsDirectoryDataSource.h @@ -0,0 +1,164 @@ +/* -*- 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 "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) 1999 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIRDFDataSource.h" +#include "nsIRDFService.h" +#include "nsIAbListener.h" +#include "nsIAbDirectory.h" +#include "nsIAbCard.h" + +static const char kAddrBookRootURI[] = "abdirectory:/"; + + +/** + * The addressbook data source. + */ +class nsABDirectoryDataSource : public nsIRDFDataSource, + public nsIAbListener +{ +private: + char* mURI; + nsVoidArray* mObservers; + PRBool mInitialized; + + // The cached service managers + + nsIRDFService* mRDFService; + +public: + + NS_DECL_ISUPPORTS + + nsABDirectoryDataSource(void); + virtual ~nsABDirectoryDataSource (void); + + + // nsIRDFDataSource methods + NS_IMETHOD Init(const char* uri); + + NS_IMETHOD GetURI(char* *uri); + + NS_IMETHOD GetSource(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsIRDFResource** source /* out */); + + NS_IMETHOD GetTarget(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsIRDFNode** target); + + NS_IMETHOD GetSources(nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + nsISimpleEnumerator** sources); + + NS_IMETHOD GetTargets(nsIRDFResource* source, + nsIRDFResource* property, + PRBool tv, + nsISimpleEnumerator** targets); + + NS_IMETHOD Assert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv); + + NS_IMETHOD Unassert(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target); + + NS_IMETHOD HasAssertion(nsIRDFResource* source, + nsIRDFResource* property, + nsIRDFNode* target, + PRBool tv, + PRBool* hasAssertion); + + NS_IMETHOD AddObserver(nsIRDFObserver* n); + + NS_IMETHOD RemoveObserver(nsIRDFObserver* n); + + NS_IMETHOD ArcLabelsIn(nsIRDFNode* node, + nsISimpleEnumerator** labels); + + NS_IMETHOD ArcLabelsOut(nsIRDFResource* source, + nsISimpleEnumerator** labels); + + NS_IMETHOD GetAllResources(nsISimpleEnumerator** aCursor); + + NS_IMETHOD Flush(); + + NS_IMETHOD GetAllCommands(nsIRDFResource* source, + nsIEnumerator/**/** commands); + + NS_IMETHOD IsCommandEnabled(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments, + PRBool* aResult); + + NS_IMETHOD DoCommand(nsISupportsArray/**/* aSources, + nsIRDFResource* aCommand, + nsISupportsArray/**/* aArguments); + + NS_IMETHOD OnItemAdded(nsIAbBase *parentDirectory, nsISupports *item); + + NS_IMETHOD OnItemRemoved(nsIAbBase *parentDirectory, nsISupports *item); + + NS_IMETHOD OnItemPropertyChanged(nsISupports *item, const char *property, + const char *oldValue, const char *newValue); + + // caching frequently used resources +protected: + + void createNode(nsString& str, nsIRDFNode **node); + void createNode(PRUint32 value, nsIRDFNode **node); + nsresult NotifyPropertyChanged(nsIRDFResource *resource, nsIRDFResource *propertyResource, + const char *oldValue, const char *newValue); + + nsresult NotifyObservers(nsIRDFResource *subject, nsIRDFResource *property, + nsIRDFNode *object, PRBool assert); + nsresult createDirectoryNode(nsIAbDirectory* directory, + nsIRDFResource* property, + nsIRDFNode** target); + nsresult createDirectoryNameNode(nsIAbDirectory *directory, + nsIRDFNode **target); + nsresult createDirectoryChildNode(nsIAbDirectory *directory, + nsIRDFNode **target); + nsresult createCardChildNode(nsIAbDirectory *directory, + nsIRDFNode **target); + static nsresult getDirectoryArcLabelsOut(nsIAbDirectory *directory, + nsISupportsArray **arcs); + + nsresult DoDeleteFromDirectory(nsIAbDirectory *directory, + nsISupportsArray *arguments); + + nsresult DoNewDirectory(nsIAbDirectory *directory, + nsISupportsArray *arguments); + + static PRBool assertEnumFunc(void *aElement, void *aData); + static PRBool unassertEnumFunc(void *aElement, void *aData); + + static nsIRDFResource* kNC_Child; + static nsIRDFResource* kNC_DirName; + static nsIRDFResource* kNC_DirChild; + static nsIRDFResource* kNC_CardChild; + + // commands + static nsIRDFResource* kNC_Delete; + static nsIRDFResource* kNC_NewDirectory; + +};