Back to index

lightning-sunbird  0.9+nobinonly
nsSubscribeDataSource.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Seth Spitzer <sspitzer@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsSubscribeDataSource.h"
00040 
00041 #include "nsIRDFService.h"
00042 #include "nsRDFCID.h"
00043 #include "nsIComponentManager.h"
00044 #include "nsXPIDLString.h"
00045 #include "rdf.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsEnumeratorUtils.h"
00048 #include "nsString.h"
00049 #include "nsCOMPtr.h"
00050 #include "nsIMsgFolder.h"
00051 #include "nsIMsgIncomingServer.h"
00052 
00053 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
00054 
00055 // this is used for notification of observers using nsVoidArray
00056 typedef struct _nsSubscribeNotification {
00057   nsIRDFDataSource *datasource;
00058   nsIRDFResource *subject;
00059   nsIRDFResource *property;
00060   nsIRDFNode *object;
00061 } nsSubscribeNotification;
00062 
00063 nsSubscribeDataSource::nsSubscribeDataSource()
00064 {
00065 }
00066 
00067 nsSubscribeDataSource::~nsSubscribeDataSource()
00068 {
00069 }
00070 
00071 NS_IMPL_THREADSAFE_ADDREF(nsSubscribeDataSource)
00072 NS_IMPL_THREADSAFE_RELEASE(nsSubscribeDataSource)
00073 
00074 NS_IMPL_QUERY_INTERFACE2(nsSubscribeDataSource, nsIRDFDataSource, nsISubscribeDataSource) 
00075 
00076 nsresult
00077 nsSubscribeDataSource::Init()
00078 {
00079     nsresult rv;
00080 
00081     mRDFService = do_GetService(kRDFServiceCID, &rv);
00082     NS_ASSERTION(NS_SUCCEEDED(rv) && mRDFService, "failed to get rdf service");
00083     NS_ENSURE_SUCCESS(rv,rv);
00084     if (!mRDFService) return NS_ERROR_FAILURE;
00085 
00086     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
00087                                   getter_AddRefs(kNC_Child));
00088     NS_ENSURE_SUCCESS(rv,rv);
00089 
00090     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
00091                                   getter_AddRefs(kNC_Name));
00092     NS_ENSURE_SUCCESS(rv,rv);
00093 
00094     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "LeafName"),
00095                                   getter_AddRefs(kNC_LeafName));
00096     NS_ENSURE_SUCCESS(rv,rv);
00097 
00098     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Subscribed"),
00099                                   getter_AddRefs(kNC_Subscribed));
00100     NS_ENSURE_SUCCESS(rv,rv);
00101 
00102     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Subscribable"),
00103                                   getter_AddRefs(kNC_Subscribable));
00104     NS_ENSURE_SUCCESS(rv,rv);
00105 
00106     rv = mRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "ServerType"),
00107                                   getter_AddRefs(kNC_ServerType));
00108     NS_ENSURE_SUCCESS(rv,rv);
00109 
00110     rv = mRDFService->GetLiteral(NS_LITERAL_STRING("true").get(),getter_AddRefs(kTrueLiteral));
00111     NS_ENSURE_SUCCESS(rv,rv);
00112   
00113     rv = mRDFService->GetLiteral(NS_LITERAL_STRING("false").get(),getter_AddRefs(kFalseLiteral));
00114     NS_ENSURE_SUCCESS(rv,rv);
00115        return NS_OK;
00116 }
00117 
00118 NS_IMETHODIMP 
00119 nsSubscribeDataSource::GetURI(char * *aURI)
00120 {
00121   if ((*aURI = nsCRT::strdup("rdf:subscribe")) == nsnull)
00122     return NS_ERROR_OUT_OF_MEMORY;
00123   else
00124     return NS_OK;
00125 }
00126 
00127 NS_IMETHODIMP 
00128 nsSubscribeDataSource::GetSource(nsIRDFResource *property, nsIRDFNode *target, PRBool tv, nsIRDFResource **source)
00129 {
00130     NS_PRECONDITION(property != nsnull, "null ptr");
00131     if (! property)
00132         return NS_ERROR_NULL_POINTER;
00133 
00134     NS_PRECONDITION(target != nsnull, "null ptr");
00135     if (! target)
00136         return NS_ERROR_NULL_POINTER;
00137 
00138     NS_PRECONDITION(source != nsnull, "null ptr");
00139     if (! source)
00140         return NS_ERROR_NULL_POINTER;
00141 
00142     *source = nsnull;
00143     return NS_RDF_NO_VALUE;
00144 }
00145 
00146 NS_IMETHODIMP
00147 nsSubscribeDataSource::GetTarget(nsIRDFResource *source,
00148                                 nsIRDFResource *property,
00149                                 PRBool tv,
00150                                 nsIRDFNode **target /* out */)
00151 {
00152        nsresult rv = NS_RDF_NO_VALUE;
00153 
00154        NS_PRECONDITION(source != nsnull, "null ptr");
00155        if (! source)
00156               return NS_ERROR_NULL_POINTER;
00157 
00158        NS_PRECONDITION(property != nsnull, "null ptr");
00159        if (! property)
00160               return NS_ERROR_NULL_POINTER;
00161 
00162        NS_PRECONDITION(target != nsnull, "null ptr");
00163        if (! target)
00164               return NS_ERROR_NULL_POINTER;
00165 
00166        *target = nsnull;
00167 
00168        // we only have positive assertions in the subscribe data source.
00169        if (! tv) return NS_RDF_NO_VALUE;
00170 
00171     nsCOMPtr<nsISubscribableServer> server;
00172     nsXPIDLCString relativePath;
00173 
00174     rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
00175     if (NS_FAILED(rv) || !server) {
00176         return NS_RDF_NO_VALUE;
00177     }
00178 
00179     if (property == kNC_Name.get()) {
00180         nsCOMPtr<nsIRDFLiteral> name;
00181         rv = mRDFService->GetLiteral(NS_ConvertUTF8toUTF16(relativePath).get(),
00182                                      getter_AddRefs(name));
00183         NS_ENSURE_SUCCESS(rv,rv);
00184 
00185         if (!name) rv = NS_RDF_NO_VALUE;
00186         if (rv == NS_RDF_NO_VALUE) return(rv);
00187         return name->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00188     }
00189     else if (property == kNC_Child.get()) {
00190         nsXPIDLCString childUri;
00191         rv = server->GetFirstChildURI(relativePath, childUri);
00192         if (NS_FAILED(rv)) return NS_RDF_NO_VALUE;
00193         if (childUri.IsEmpty()) return NS_RDF_NO_VALUE;
00194 
00195         nsCOMPtr <nsIRDFResource> childResource;
00196         rv = mRDFService->GetResource(childUri, getter_AddRefs(childResource));
00197         NS_ENSURE_SUCCESS(rv,rv);
00198         
00199         return childResource->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00200     }
00201     else if (property == kNC_Subscribed.get()) {
00202         PRBool isSubscribed;
00203         rv = server->IsSubscribed(relativePath, &isSubscribed);
00204         NS_ENSURE_SUCCESS(rv,rv);
00205     
00206         NS_IF_ADDREF(*target = (isSubscribed ? kTrueLiteral : kFalseLiteral));
00207         return NS_OK;
00208     }
00209     else if (property == kNC_Subscribable.get()) {
00210         PRBool isSubscribable;
00211         rv = server->IsSubscribable(relativePath, &isSubscribable);
00212         NS_ENSURE_SUCCESS(rv,rv);
00213         
00214         NS_IF_ADDREF(*target = (isSubscribable ? kTrueLiteral : kFalseLiteral));
00215         return NS_OK;
00216     }
00217     else if (property == kNC_ServerType.get()) {
00218         nsXPIDLCString serverTypeStr;
00219         rv = GetServerType(server, getter_Copies(serverTypeStr));
00220         NS_ENSURE_SUCCESS(rv,rv);
00221 
00222         nsCOMPtr<nsIRDFLiteral> serverType;
00223         rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(serverTypeStr).get(),
00224                                      getter_AddRefs(serverType));
00225         NS_ENSURE_SUCCESS(rv,rv);
00226 
00227         if (!serverType) rv = NS_RDF_NO_VALUE;
00228         if (rv == NS_RDF_NO_VALUE) return(rv);
00229         return serverType->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00230     }
00231     else if (property == kNC_LeafName.get()) {
00232         nsXPIDLString leafNameStr;
00233         rv = server->GetLeafName(relativePath, leafNameStr); 
00234         NS_ENSURE_SUCCESS(rv,rv);
00235    
00236         nsCOMPtr<nsIRDFLiteral> leafName;
00237         rv = mRDFService->GetLiteral(leafNameStr, getter_AddRefs(leafName));
00238         NS_ENSURE_SUCCESS(rv,rv);
00239 
00240         if (!leafName) rv = NS_RDF_NO_VALUE;
00241         if (rv == NS_RDF_NO_VALUE) return(rv);
00242         return leafName->QueryInterface(NS_GET_IID(nsIRDFNode), (void**) target);
00243     }
00244     else {
00245         // do nothing
00246     }
00247 
00248        return(NS_RDF_NO_VALUE);
00249 }
00250 
00251 nsresult
00252 nsSubscribeDataSource::GetChildren(nsISubscribableServer *aServer, 
00253                                    const nsACString &aRelativePath,
00254                                    nsISimpleEnumerator** aResult)
00255 {
00256     nsresult rv = NS_OK;
00257     NS_ASSERTION(aServer && aResult, "no server or result");
00258     if (!aServer || !aResult) return NS_ERROR_NULL_POINTER;       
00259 
00260     nsCOMPtr<nsISupportsArray> children;
00261     rv = NS_NewISupportsArray(getter_AddRefs(children));
00262     NS_ENSURE_SUCCESS(rv,rv);
00263     if (!children) return NS_ERROR_FAILURE;
00264 
00265     rv = aServer->GetChildren(aRelativePath, children);
00266     // GetChildren() can fail if there are no children
00267     if (NS_FAILED(rv)) return rv;
00268 
00269     nsISimpleEnumerator* result = new nsArrayEnumerator(children);
00270     if (!result) return NS_ERROR_OUT_OF_MEMORY;
00271 
00272     NS_ADDREF(result);
00273     *aResult = result;
00274 
00275     return NS_OK;
00276 }
00277 
00278 NS_IMETHODIMP
00279 nsSubscribeDataSource::GetTargets(nsIRDFResource *source,
00280                             nsIRDFResource *property,
00281                             PRBool tv,
00282                             nsISimpleEnumerator **targets /* out */)
00283 {
00284        nsresult rv = NS_OK;
00285 
00286        NS_PRECONDITION(source != nsnull, "null ptr");
00287        if (! source)
00288               return NS_ERROR_NULL_POINTER;
00289 
00290        NS_PRECONDITION(property != nsnull, "null ptr");
00291        if (! property)
00292               return NS_ERROR_NULL_POINTER;
00293 
00294        NS_PRECONDITION(targets != nsnull, "null ptr");
00295        if (! targets)
00296               return NS_ERROR_NULL_POINTER;
00297 
00298     *targets = nsnull;
00299 
00300        // we only have positive assertions in the subscribe data source.
00301        if (!tv) return NS_RDF_NO_VALUE;
00302 
00303     nsCOMPtr<nsISubscribableServer> server;
00304     nsXPIDLCString relativePath;  // UTF-8
00305 
00306     rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
00307     if (NS_FAILED(rv) || !server) {
00308            return NS_NewEmptyEnumerator(targets);
00309     }
00310 
00311     if (property == kNC_Child.get()) {
00312         rv = GetChildren(server, relativePath, targets);
00313         if (NS_FAILED(rv)) {
00314             return NS_NewEmptyEnumerator(targets);
00315         }
00316         return rv;
00317     }
00318     else if (property == kNC_LeafName.get()) {
00319         nsXPIDLString leafNameStr;
00320         rv = server->GetLeafName(relativePath, leafNameStr);
00321         NS_ENSURE_SUCCESS(rv,rv);
00322     
00323         nsCOMPtr<nsIRDFLiteral> leafName;
00324         rv = mRDFService->GetLiteral(leafNameStr, getter_AddRefs(leafName));
00325         NS_ENSURE_SUCCESS(rv,rv);
00326 
00327         nsISimpleEnumerator* result = new nsSingletonEnumerator(leafName);
00328         if (!result) return NS_ERROR_OUT_OF_MEMORY;
00329 
00330         NS_IF_ADDREF(*targets = result);
00331         return NS_OK;
00332     }
00333     else if (property == kNC_Subscribed.get()) {
00334         PRBool isSubscribed;
00335         rv = server->IsSubscribed(relativePath, &isSubscribed);
00336         NS_ENSURE_SUCCESS(rv,rv);
00337 
00338         nsISimpleEnumerator* result = new nsSingletonEnumerator(isSubscribed ? kTrueLiteral : kFalseLiteral);
00339         if (!result) return NS_ERROR_OUT_OF_MEMORY;
00340 
00341         NS_IF_ADDREF(*targets = result);
00342         return NS_OK;
00343     }
00344     else if (property == kNC_Subscribable.get()) {
00345         PRBool isSubscribable;
00346         rv = server->IsSubscribable(relativePath, &isSubscribable);
00347         NS_ENSURE_SUCCESS(rv,rv);
00348 
00349         nsISimpleEnumerator* result = new nsSingletonEnumerator(isSubscribable ? kTrueLiteral : kFalseLiteral);
00350         if (!result) return NS_ERROR_OUT_OF_MEMORY;
00351 
00352         NS_IF_ADDREF(*targets = result);
00353         return NS_OK;
00354     }
00355     else if (property == kNC_Name.get()) {
00356         nsCOMPtr<nsIRDFLiteral> name;
00357         rv = mRDFService->GetLiteral(NS_ConvertUTF8toUTF16(relativePath).get(),
00358                                      getter_AddRefs(name));
00359         NS_ENSURE_SUCCESS(rv,rv);
00360 
00361         nsISimpleEnumerator* result = new nsSingletonEnumerator(name);
00362         if (!result) return NS_ERROR_OUT_OF_MEMORY;
00363 
00364         NS_IF_ADDREF(*targets = result);
00365         return NS_OK;
00366     }
00367     else if (property == kNC_ServerType.get()) {
00368         nsXPIDLCString serverTypeStr;
00369         rv = GetServerType(server, getter_Copies(serverTypeStr));
00370         NS_ENSURE_SUCCESS(rv,rv);
00371 
00372         nsCOMPtr<nsIRDFLiteral> serverType;
00373         rv = mRDFService->GetLiteral(NS_ConvertASCIItoUTF16(serverTypeStr).get(),
00374                                      getter_AddRefs(serverType));
00375         NS_ENSURE_SUCCESS(rv,rv);
00376 
00377         nsISimpleEnumerator* result = new nsSingletonEnumerator(serverType);
00378         if (!result) return NS_ERROR_OUT_OF_MEMORY;
00379 
00380         NS_IF_ADDREF(*targets = result);
00381         return NS_OK;
00382     }
00383     else {
00384         // do nothing
00385     }
00386 
00387        return NS_NewEmptyEnumerator(targets);
00388 }
00389 
00390 NS_IMETHODIMP
00391 nsSubscribeDataSource::Assert(nsIRDFResource *source,
00392                        nsIRDFResource *property,
00393                        nsIRDFNode *target,
00394                        PRBool tv)
00395 {
00396        return NS_RDF_ASSERTION_REJECTED;
00397 }
00398 
00399 
00400 
00401 NS_IMETHODIMP
00402 nsSubscribeDataSource::Unassert(nsIRDFResource *source,
00403                          nsIRDFResource *property,
00404                          nsIRDFNode *target)
00405 {
00406        return NS_RDF_ASSERTION_REJECTED;
00407 }
00408 
00409 
00410 
00411 NS_IMETHODIMP
00412 nsSubscribeDataSource::Change(nsIRDFResource* aSource,
00413                                                   nsIRDFResource* aProperty,
00414                                                   nsIRDFNode* aOldTarget,
00415                                                   nsIRDFNode* aNewTarget)
00416 {
00417        return NS_RDF_ASSERTION_REJECTED;
00418 }
00419 
00420 
00421 
00422 NS_IMETHODIMP
00423 nsSubscribeDataSource::Move(nsIRDFResource* aOldSource,
00424                                              nsIRDFResource* aNewSource,
00425                                              nsIRDFResource* aProperty,
00426                                              nsIRDFNode* aTarget)
00427 {
00428        return NS_RDF_ASSERTION_REJECTED;
00429 }
00430 
00431 nsresult
00432 nsSubscribeDataSource::GetServerType(nsISubscribableServer *server, char **serverType)
00433 {
00434     nsresult rv;
00435 
00436     if (!server || !serverType) return NS_ERROR_NULL_POINTER;
00437     nsCOMPtr<nsIMsgIncomingServer> incomingServer(do_QueryInterface(server, &rv));
00438     NS_ENSURE_SUCCESS(rv,rv);
00439     if (!incomingServer) return NS_ERROR_FAILURE;
00440 
00441     rv = incomingServer->GetType(serverType);
00442     NS_ENSURE_SUCCESS(rv,rv);
00443     
00444     return NS_OK;
00445 }
00446 
00447 nsresult
00448 nsSubscribeDataSource::GetServerAndRelativePathFromResource(nsIRDFResource *source, nsISubscribableServer **server, char **relativePath)
00449 {
00450     nsresult rv = NS_OK;
00451 
00452     const char *sourceURI = nsnull;
00453     rv = source->GetValueConst(&sourceURI);
00454     NS_ENSURE_SUCCESS(rv,rv);
00455 
00456     nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(source, &rv));
00457     // we expect this to fail sometimes, so don't assert
00458     if (NS_FAILED(rv)) return rv;
00459     if (!folder) return NS_ERROR_FAILURE;
00460 
00461     nsCOMPtr<nsIMsgIncomingServer> incomingServer;
00462     rv = folder->GetServer(getter_AddRefs(incomingServer));
00463     NS_ENSURE_SUCCESS(rv,rv);
00464     if (!incomingServer) return NS_ERROR_FAILURE;
00465 
00466     rv = incomingServer->QueryInterface(NS_GET_IID(nsISubscribableServer), (void**)server);
00467     NS_ENSURE_SUCCESS(rv,rv);
00468     if (!*server) return NS_ERROR_FAILURE;
00469 
00470     nsXPIDLCString serverURI;
00471     rv = incomingServer->GetServerURI(getter_Copies(serverURI));
00472     NS_ENSURE_SUCCESS(rv,rv);
00473  
00474     PRUint32 serverURILen = strlen((const char *)serverURI);   
00475     if (serverURILen == strlen(sourceURI)) {
00476         *relativePath = nsnull;
00477     }
00478     else {
00479         // XXX : perhaps, have to unescape before returning 
00480         *relativePath = nsCRT::strdup(sourceURI + serverURILen + 1);
00481         NS_ASSERTION(*relativePath,"no relative path");
00482         if (!*relativePath) return NS_ERROR_OUT_OF_MEMORY;
00483     }
00484 
00485     return NS_OK;
00486 }
00487 
00488 NS_IMETHODIMP
00489 nsSubscribeDataSource::HasAssertion(nsIRDFResource *source,
00490                              nsIRDFResource *property,
00491                              nsIRDFNode *target,
00492                              PRBool tv,
00493                              PRBool *hasAssertion /* out */)
00494 {
00495     nsresult rv = NS_OK;
00496 
00497        NS_PRECONDITION(source != nsnull, "null ptr");
00498        if (! source)
00499               return NS_ERROR_NULL_POINTER;
00500 
00501        NS_PRECONDITION(property != nsnull, "null ptr");
00502        if (! property)
00503               return NS_ERROR_NULL_POINTER;
00504 
00505        NS_PRECONDITION(target != nsnull, "null ptr");
00506        if (! target)
00507               return NS_ERROR_NULL_POINTER;
00508 
00509        NS_PRECONDITION(hasAssertion != nsnull, "null ptr");
00510        if (! hasAssertion)
00511               return NS_ERROR_NULL_POINTER;
00512 
00513        *hasAssertion = PR_FALSE;
00514 
00515   // we only have positive assertions in the subscribe data source.
00516        if (!tv) return NS_OK;
00517 
00518        if (property == kNC_Child.get()) {
00519     nsCOMPtr<nsISubscribableServer> server;
00520     nsXPIDLCString relativePath;
00521 
00522     rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
00523     if (NS_FAILED(rv) || !server) {
00524         *hasAssertion = PR_FALSE;
00525         return NS_OK;
00526     }
00527 
00528         // not everything has children
00529         rv = server->HasChildren(relativePath, hasAssertion);
00530         NS_ENSURE_SUCCESS(rv,rv);
00531     }
00532     else if (property == kNC_Name.get()) {
00533         // everything has a name
00534         *hasAssertion = PR_TRUE;
00535     }
00536     else if (property == kNC_LeafName.get()) {
00537         // everything has a leaf name
00538         *hasAssertion = PR_TRUE;
00539     }
00540     else if (property == kNC_Subscribed.get()) {
00541         // everything is subscribed or not
00542         *hasAssertion = PR_TRUE;
00543     }
00544     else if (property == kNC_Subscribable.get()) {
00545         // everything is subscribable or not
00546         *hasAssertion = PR_TRUE;
00547     }
00548     else if (property == kNC_ServerType.get()) {
00549         // everything has a server type
00550         *hasAssertion = PR_TRUE;
00551     }
00552     else {
00553         // do nothing
00554     }
00555 
00556        return NS_OK;
00557 }
00558 
00559 
00560 NS_IMETHODIMP 
00561 nsSubscribeDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
00562 {
00563     return NS_ERROR_NOT_IMPLEMENTED;
00564 }
00565 
00566 NS_IMETHODIMP 
00567 nsSubscribeDataSource::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, PRBool *result)
00568 {
00569     nsresult rv = NS_OK;
00570 
00571     nsCOMPtr<nsISubscribableServer> server;
00572     nsXPIDLCString relativePath;
00573 
00574     if (aArc == kNC_Child.get()) {
00575     rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
00576     if (NS_FAILED(rv) || !server) {
00577            *result = PR_FALSE;
00578         return NS_OK;
00579     }
00580 
00581         PRBool hasChildren = PR_FALSE;
00582         rv = server->HasChildren(relativePath, &hasChildren);
00583         NS_ENSURE_SUCCESS(rv,rv);
00584         *result = hasChildren;
00585         return NS_OK;
00586     }
00587     else if ((aArc == kNC_Subscribed.get()) ||
00588              (aArc == kNC_Subscribable.get()) ||
00589              (aArc == kNC_LeafName.get()) ||
00590              (aArc == kNC_ServerType.get()) ||
00591              (aArc == kNC_Name.get())) {
00592         *result = PR_TRUE;
00593         return NS_OK;
00594     }
00595 
00596     *result = PR_FALSE;
00597     return NS_OK;
00598 }
00599 
00600 
00601 NS_IMETHODIMP
00602 nsSubscribeDataSource::ArcLabelsIn(nsIRDFNode *node,
00603                             nsISimpleEnumerator ** labels /* out */)
00604 {
00605        return NS_ERROR_NOT_IMPLEMENTED;
00606 }
00607 
00608 
00609 
00610 NS_IMETHODIMP
00611 nsSubscribeDataSource::ArcLabelsOut(nsIRDFResource *source,
00612                                nsISimpleEnumerator **labels /* out */)
00613 {
00614     nsresult rv = NS_OK;
00615 
00616     NS_PRECONDITION(source != nsnull, "null ptr");
00617     if (! source)
00618        return NS_ERROR_NULL_POINTER;
00619 
00620     NS_PRECONDITION(labels != nsnull, "null ptr");
00621     if (! labels)
00622        return NS_ERROR_NULL_POINTER;
00623 
00624     nsCOMPtr<nsISubscribableServer> server;
00625     nsXPIDLCString relativePath;
00626 
00627     rv = GetServerAndRelativePathFromResource(source, getter_AddRefs(server), getter_Copies(relativePath));
00628     if (NS_FAILED(rv) || !server) {
00629         return NS_NewEmptyEnumerator(labels);
00630     }
00631 
00632     nsCOMPtr<nsISupportsArray> array;
00633     rv = NS_NewISupportsArray(getter_AddRefs(array));
00634     NS_ENSURE_SUCCESS(rv,rv);
00635 
00636     array->AppendElement(kNC_Subscribed);
00637     array->AppendElement(kNC_Subscribable);
00638     array->AppendElement(kNC_Name);
00639     array->AppendElement(kNC_ServerType);
00640     array->AppendElement(kNC_LeafName);
00641 
00642     PRBool hasChildren = PR_FALSE;
00643     rv = server->HasChildren(relativePath, &hasChildren);
00644     NS_ENSURE_SUCCESS(rv,rv);
00645 
00646     if (hasChildren) {
00647         array->AppendElement(kNC_Child);
00648     }
00649 
00650     nsISimpleEnumerator* result = new nsArrayEnumerator(array);
00651     if (! result) return NS_ERROR_OUT_OF_MEMORY;
00652 
00653     NS_ADDREF(result);
00654     *labels = result;
00655     return NS_OK;
00656 }
00657 
00658 NS_IMETHODIMP
00659 nsSubscribeDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
00660 {
00661        NS_NOTYETIMPLEMENTED("sorry!");
00662        return NS_ERROR_NOT_IMPLEMENTED;
00663 }
00664 
00665 
00666 
00667 NS_IMETHODIMP
00668 nsSubscribeDataSource::AddObserver(nsIRDFObserver *n)
00669 {
00670     NS_PRECONDITION(n != nsnull, "null ptr");
00671     if (! n)
00672         return NS_ERROR_NULL_POINTER;
00673 
00674        if (! mObservers)
00675        {
00676               nsresult rv;
00677               rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
00678               if (NS_FAILED(rv)) return rv;
00679        }
00680        mObservers->AppendElement(n);
00681        return NS_OK;
00682 }
00683 
00684 
00685 NS_IMETHODIMP
00686 nsSubscribeDataSource::RemoveObserver(nsIRDFObserver *n)
00687 {
00688     NS_PRECONDITION(n != nsnull, "null ptr");
00689     if (! n)
00690         return NS_ERROR_NULL_POINTER;
00691 
00692        if (! mObservers)
00693               return NS_OK;
00694 
00695        mObservers->RemoveElement(n);
00696        return NS_OK;
00697 }
00698 
00699 NS_IMETHODIMP
00700 nsSubscribeDataSource::GetHasObservers(PRBool *hasObservers)
00701 {
00702     nsresult rv = NS_OK;
00703     NS_ASSERTION(hasObservers, "null ptr");
00704     if (!hasObservers) return NS_ERROR_NULL_POINTER;
00705     
00706     if (!mObservers) {
00707         *hasObservers = PR_FALSE;
00708         return NS_OK;
00709     }
00710     
00711     PRUint32 count = 0;
00712     rv = mObservers->Count(&count);
00713     NS_ENSURE_SUCCESS(rv,rv);
00714 
00715     *hasObservers = (count > 0);
00716     return NS_OK;
00717 }
00718 
00719 NS_IMETHODIMP
00720 nsSubscribeDataSource::GetAllCmds(nsIRDFResource* source,
00721                                      nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
00722 {
00723        return(NS_NewEmptyEnumerator(commands));
00724 }
00725 
00726 NS_IMETHODIMP
00727 nsSubscribeDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00728                                        nsIRDFResource*   aCommand,
00729                                        nsISupportsArray/*<nsIRDFResource>*/* aArguments,
00730                                        PRBool* aResult)
00731 {
00732        return(NS_ERROR_NOT_IMPLEMENTED);
00733 }
00734 
00735 
00736 
00737 NS_IMETHODIMP
00738 nsSubscribeDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00739                                 nsIRDFResource*   aCommand,
00740                                 nsISupportsArray/*<nsIRDFResource>*/* aArguments)
00741 {
00742        return(NS_ERROR_NOT_IMPLEMENTED);
00743 }
00744 
00745 
00746 
00747 NS_IMETHODIMP
00748 nsSubscribeDataSource::BeginUpdateBatch()
00749 {
00750         return NS_OK;
00751 }
00752 
00753 
00754 
00755 NS_IMETHODIMP
00756 nsSubscribeDataSource::EndUpdateBatch()
00757 {
00758         return NS_OK;
00759 }
00760 
00761 
00762 
00763 NS_IMETHODIMP 
00764 nsSubscribeDataSource::GetSources(nsIRDFResource *aProperty, nsIRDFNode *aTarget, PRBool aTruthValue, nsISimpleEnumerator **_retval)
00765 {
00766   NS_ASSERTION(PR_FALSE, "Not implemented");
00767   return NS_ERROR_NOT_IMPLEMENTED;
00768 }
00769 
00770 NS_IMETHODIMP
00771 nsSubscribeDataSource::NotifyObservers(nsIRDFResource *subject,
00772                                                 nsIRDFResource *property,
00773                                                 nsIRDFNode *object,
00774                                                 PRBool assert, PRBool change)
00775 {
00776     NS_ASSERTION(!(change && assert),
00777                  "Can't change and assert at the same time!\n");
00778 
00779     if(mObservers)
00780     {
00781         nsSubscribeNotification note = { this, subject, property, object };
00782         if(change)
00783             mObservers->EnumerateForwards(changeEnumFunc, &note);
00784         else if (assert)
00785             mObservers->EnumerateForwards(assertEnumFunc, &note);
00786         else
00787             mObservers->EnumerateForwards(unassertEnumFunc, &note);
00788   }
00789     return NS_OK;
00790 }
00791 
00792 PRBool
00793 nsSubscribeDataSource::changeEnumFunc(nsISupports *aElement, void *aData)
00794 {
00795   nsSubscribeNotification* note = (nsSubscribeNotification*)aData;
00796   nsIRDFObserver* observer = (nsIRDFObserver *)aElement;
00797 
00798   observer->OnChange(note->datasource,
00799                      note->subject,
00800                      note->property,
00801                      nsnull, note->object);
00802   return PR_TRUE;
00803 }
00804 
00805 PRBool
00806 nsSubscribeDataSource::assertEnumFunc(nsISupports *aElement, void *aData)
00807 {
00808   nsSubscribeNotification* note = (nsSubscribeNotification*)aData;
00809   nsIRDFObserver* observer = (nsIRDFObserver *)aElement;
00810 
00811   observer->OnAssert(note->datasource,
00812                      note->subject,
00813                      note->property,
00814                      note->object);
00815   return PR_TRUE;
00816 }
00817 
00818 PRBool
00819 nsSubscribeDataSource::unassertEnumFunc(nsISupports *aElement, void *aData)
00820 {
00821   nsSubscribeNotification* note = (nsSubscribeNotification*)aData;
00822   nsIRDFObserver* observer = (nsIRDFObserver *)aElement;
00823 
00824   observer->OnUnassert(note->datasource,
00825                        note->subject,
00826                        note->property,
00827                        note->object);
00828   return PR_TRUE;
00829 }