Back to index

lightning-sunbird  0.9+nobinonly
nsLocalSearchService.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8; c-file-style: "stroustrup" -*- */
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  *   Robert John Churchill      <rjc@netscape.com>
00024  *   Pierre Phaneuf             <pp@ludusdesign.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /*
00041   Implementation for a find RDF data store.
00042  */
00043 
00044 #include "nsLocalSearchService.h"
00045 #include "nscore.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsIRDFContainerUtils.h"
00048 #include "nsEnumeratorUtils.h"
00049 #include "nsXPIDLString.h"
00050 #include "nsReadableUtils.h"
00051 #include "nsUnicharUtils.h"
00052 #include "plhash.h"
00053 #include "plstr.h"
00054 #include "prmem.h"
00055 #include "prprf.h"
00056 #include "prio.h"
00057 #include "prlog.h"
00058 #include "nsITextToSubURI.h"
00059 #include "nsIRDFObserver.h"
00060 #include "nsRDFCID.h"
00061 #include "rdf.h"
00062 #include "nsCRT.h"
00063 
00064 static NS_DEFINE_CID(kRDFServiceCID,               NS_RDFSERVICE_CID);
00065 static NS_DEFINE_CID(kTextToSubURICID,             NS_TEXTTOSUBURI_CID);
00066 
00067 static nsIRDFService        *gRDFService = nsnull;
00068 static LocalSearchDataSource              *gLocalSearchDataSource = nsnull;
00069 static const char    kFindProtocol[] = "find:";
00070 
00071 static PRBool
00072 isFindURI(nsIRDFResource *r)
00073 {
00074        PRBool        isFindURIFlag = PR_FALSE;
00075        const char    *uri = nsnull;
00076        
00077        r->GetValueConst(&uri);
00078        if ((uri) && (!strncmp(uri, kFindProtocol, sizeof(kFindProtocol) - 1)))
00079        {
00080               isFindURIFlag = PR_TRUE;
00081        }
00082        return(isFindURIFlag);
00083 }
00084 
00085 
00086 PRInt32              LocalSearchDataSource::gRefCnt;
00087 nsIRDFResource              *LocalSearchDataSource::kNC_Child;
00088 nsIRDFResource              *LocalSearchDataSource::kNC_Name;
00089 nsIRDFResource              *LocalSearchDataSource::kNC_URL;
00090 nsIRDFResource              *LocalSearchDataSource::kNC_FindObject;
00091 nsIRDFResource              *LocalSearchDataSource::kNC_pulse;
00092 nsIRDFResource              *LocalSearchDataSource::kRDF_InstanceOf;
00093 nsIRDFResource              *LocalSearchDataSource::kRDF_type;
00094 
00095 LocalSearchDataSource::LocalSearchDataSource(void)
00096 {
00097        if (gRefCnt++ == 0)
00098        {
00099               nsresult rv = CallGetService(kRDFServiceCID, &gRDFService);
00100 
00101               PR_ASSERT(NS_SUCCEEDED(rv));
00102 
00103               gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "child"),
00104                              &kNC_Child);
00105               gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "Name"),
00106                              &kNC_Name);
00107               gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "URL"),
00108                              &kNC_URL);
00109               gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "FindObject"),
00110                              &kNC_FindObject);
00111               gRDFService->GetResource(NS_LITERAL_CSTRING(NC_NAMESPACE_URI "pulse"),
00112                              &kNC_pulse);
00113 
00114               gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "instanceOf"),
00115                              &kRDF_InstanceOf);
00116               gRDFService->GetResource(NS_LITERAL_CSTRING(RDF_NAMESPACE_URI "type"),
00117                              &kRDF_type);
00118 
00119               gLocalSearchDataSource = this;
00120        }
00121 }
00122 
00123 
00124 
00125 LocalSearchDataSource::~LocalSearchDataSource (void)
00126 {
00127        if (--gRefCnt == 0)
00128        {
00129               NS_RELEASE(kNC_Child);
00130               NS_RELEASE(kNC_Name);
00131               NS_RELEASE(kNC_URL);
00132               NS_RELEASE(kNC_FindObject);
00133               NS_RELEASE(kNC_pulse);
00134               NS_RELEASE(kRDF_InstanceOf);
00135               NS_RELEASE(kRDF_type);
00136 
00137               gLocalSearchDataSource = nsnull;
00138               NS_RELEASE(gRDFService);
00139        }
00140 }
00141 
00142 
00143 
00144 nsresult
00145 LocalSearchDataSource::Init()
00146 {
00147        nsresult      rv = NS_ERROR_OUT_OF_MEMORY;
00148 
00149        // register this as a named data source with the service manager
00150        if (NS_FAILED(rv = gRDFService->RegisterDataSource(this, PR_FALSE)))
00151               return(rv);
00152 
00153        return(rv);
00154 }
00155 
00156 
00157 
00158 NS_IMPL_ISUPPORTS1(LocalSearchDataSource, nsIRDFDataSource)
00159 
00160 
00161 
00162 NS_IMETHODIMP
00163 LocalSearchDataSource::GetURI(char **uri)
00164 {
00165        NS_PRECONDITION(uri != nsnull, "null ptr");
00166        if (! uri)
00167               return NS_ERROR_NULL_POINTER;
00168 
00169        if ((*uri = nsCRT::strdup("rdf:localsearch")) == nsnull)
00170               return NS_ERROR_OUT_OF_MEMORY;
00171 
00172        return NS_OK;
00173 }
00174 
00175 
00176 
00177 NS_IMETHODIMP
00178 LocalSearchDataSource::GetSource(nsIRDFResource* property,
00179                           nsIRDFNode* target,
00180                           PRBool tv,
00181                           nsIRDFResource** source /* out */)
00182 {
00183        NS_PRECONDITION(property != nsnull, "null ptr");
00184        if (! property)
00185               return NS_ERROR_NULL_POINTER;
00186 
00187        NS_PRECONDITION(target != nsnull, "null ptr");
00188        if (! target)
00189               return NS_ERROR_NULL_POINTER;
00190 
00191        NS_PRECONDITION(source != nsnull, "null ptr");
00192        if (! source)
00193               return NS_ERROR_NULL_POINTER;
00194 
00195        *source = nsnull;
00196        return NS_RDF_NO_VALUE;
00197 }
00198 
00199 
00200 
00201 NS_IMETHODIMP
00202 LocalSearchDataSource::GetSources(nsIRDFResource *property,
00203                            nsIRDFNode *target,
00204                         PRBool tv,
00205                            nsISimpleEnumerator **sources /* out */)
00206 {
00207        NS_NOTYETIMPLEMENTED("write me");
00208        return NS_ERROR_NOT_IMPLEMENTED;
00209 }
00210 
00211 
00212 
00213 NS_IMETHODIMP
00214 LocalSearchDataSource::GetTarget(nsIRDFResource *source,
00215                           nsIRDFResource *property,
00216                           PRBool tv,
00217                           nsIRDFNode **target /* out */)
00218 {
00219        NS_PRECONDITION(source != nsnull, "null ptr");
00220        if (! source)
00221               return NS_ERROR_NULL_POINTER;
00222 
00223        NS_PRECONDITION(property != nsnull, "null ptr");
00224        if (! property)
00225               return NS_ERROR_NULL_POINTER;
00226 
00227        NS_PRECONDITION(target != nsnull, "null ptr");
00228        if (! target)
00229               return NS_ERROR_NULL_POINTER;
00230 
00231        nsresult             rv = NS_RDF_NO_VALUE;
00232 
00233        // we only have positive assertions in the find data source.
00234        if (! tv)
00235               return rv;
00236 
00237        if (isFindURI(source))
00238        {
00239               if (property == kNC_Name)
00240               {
00241 //                   rv = GetName(source, &array);
00242               }
00243               else if (property == kNC_URL)
00244               {
00245                      // note: lie and say there is no URL
00246 //                   rv = GetURL(source, &array);
00247                      nsAutoString  url;
00248                      nsIRDFLiteral *literal;
00249                      gRDFService->GetLiteral(url.get(), &literal);
00250                      *target = literal;
00251                      return(NS_OK);
00252               }
00253               else if (property == kRDF_type)
00254               {
00255                      const char    *uri = nsnull;
00256                      rv = kNC_FindObject->GetValueConst(&uri);
00257                      if (NS_FAILED(rv)) return rv;
00258 
00259                      nsAutoString  url; url.AssignWithConversion(uri);
00260                      nsIRDFLiteral *literal;
00261                      gRDFService->GetLiteral(url.get(), &literal);
00262 
00263                      *target = literal;
00264                      return(NS_OK);
00265               }
00266               else if (property == kNC_pulse)
00267               {
00268                      nsAutoString  pulse(NS_LITERAL_STRING("15"));
00269                      nsIRDFLiteral *pulseLiteral;
00270                      rv = gRDFService->GetLiteral(pulse.get(), &pulseLiteral);
00271                      if (NS_FAILED(rv)) return rv;
00272 
00273                      *target = pulseLiteral;
00274                      return(NS_OK);
00275               }
00276               else if (property == kNC_Child)
00277               {
00278                      // fake out the generic builder (i.e. return anything in this case)
00279                      // so that search containers never appear to be empty
00280                      *target = source;
00281                      NS_ADDREF(*target);
00282                      return(NS_OK);
00283               }
00284        }
00285        return NS_RDF_NO_VALUE;
00286 }
00287 
00288 
00289 
00290 NS_METHOD
00291 LocalSearchDataSource::parseResourceIntoFindTokens(nsIRDFResource *u, findTokenPtr tokens)
00292 {
00293        const char           *uri = nsnull;
00294        char                 *id, *token, *value, *newstr;
00295        int                  loop;
00296        nsresult             rv;
00297 
00298        if (NS_FAILED(rv = u->GetValueConst(&uri)))      return(rv);
00299 
00300 #ifdef DEBUG
00301        printf("Find: %s\n", (const char*) uri);
00302 #endif
00303 
00304        if (!(id = PL_strdup(uri + sizeof(kFindProtocol) - 1)))
00305               return(NS_ERROR_OUT_OF_MEMORY);
00306 
00307        /* parse ID, build up token list */
00308        if ((token = nsCRT::strtok(id, "&", &newstr)) != NULL)
00309        {
00310               while (token != NULL)
00311               {
00312                      if ((value = strstr(token, "=")) != NULL)
00313                      {
00314                             *value++ = '\0';
00315                      }
00316                      for (loop=0; tokens[loop].token != NULL; loop++)
00317                      {
00318                             if (!strcmp(token, tokens[loop].token))
00319                             {
00320                                 if (!strcmp(token, "text"))
00321                                 {
00322                             nsCOMPtr<nsITextToSubURI> textToSubURI = 
00323                                      do_GetService(kTextToSubURICID, &rv);
00324                             if (NS_SUCCEEDED(rv) && (textToSubURI))
00325                             {
00326                                    PRUnichar     *uni = nsnull;
00327                                    if (NS_SUCCEEDED(rv = textToSubURI->UnEscapeAndConvert("UTF-8", value, &uni)) && (uni))
00328                                    {
00329                                            tokens[loop].value = uni;
00330                                            Recycle(uni);
00331                                        }
00332                                    }
00333                                 }
00334                                 else
00335                                 {
00336                                     nsAutoString    valueStr;
00337                                     valueStr.AssignWithConversion(value);
00338                                     tokens[loop].value = valueStr;
00339                          }
00340                                    break;
00341                             }
00342                      }
00343                      token = nsCRT::strtok(newstr, "&", &newstr);
00344               }
00345        }
00346        PL_strfree(id);
00347        return(NS_OK);
00348 }
00349 
00350 
00351 
00352 PRBool
00353 LocalSearchDataSource::doMatch(nsIRDFLiteral *literal,
00354                                const nsAString &matchMethod,
00355                                const nsString &matchText)
00356 {
00357        PRBool        found = PR_FALSE;
00358 
00359        if ((nsnull == literal) ||
00360             matchMethod.IsEmpty() ||
00361             matchText.IsEmpty())
00362               return(found);
00363 
00364        const  PRUnichar     *str = nsnull;
00365        literal->GetValueConst( &str );
00366        if (! str)    return(found);
00367        nsAutoString  value(str);
00368 
00369         if (matchMethod.EqualsLiteral("contains"))
00370        {
00371             if (FindInReadable(matchText, value,
00372                                nsCaseInsensitiveStringComparator()))
00373                 found = PR_TRUE;
00374        }
00375         else if (matchMethod.EqualsLiteral("startswith"))
00376        {
00377             nsAString::const_iterator start, realstart, end;
00378             value.BeginReading(start);
00379             value.EndReading(end);
00380             realstart = start;
00381             
00382             if (FindInReadable(matchText, start, end,
00383                                nsCaseInsensitiveStringComparator()) &&
00384                 start == realstart)
00385                 
00386                 found = PR_TRUE;
00387        }
00388         else if (matchMethod.EqualsLiteral("endswith"))
00389        {
00390             nsAString::const_iterator start, end, realend;
00391             value.BeginReading(start);
00392             value.EndReading(end);
00393             realend = end;
00394 
00395             if (RFindInReadable(matchText, start, end,
00396                                 nsCaseInsensitiveStringComparator()) &&
00397                 end == realend)
00398                 
00399                 found = PR_TRUE;
00400        }
00401         else if (matchMethod.EqualsLiteral("is"))
00402        {
00403             if (value.Equals(matchText, nsCaseInsensitiveStringComparator()))
00404                 found = PR_TRUE;
00405        }
00406         else if (matchMethod.EqualsLiteral("isnot"))
00407        {
00408             if (!value.Equals(matchText, nsCaseInsensitiveStringComparator()))
00409                 found = PR_TRUE;
00410        }
00411         else if (matchMethod.EqualsLiteral("doesntcontain"))
00412        {
00413             if (!FindInReadable(matchText, value,
00414                                 nsCaseInsensitiveStringComparator()))
00415                 found = PR_TRUE;
00416        }
00417         return(found);
00418 }
00419 
00420 PRBool
00421 LocalSearchDataSource::doDateMatch(nsIRDFDate *aDate,
00422                                    const nsAString& matchMethod,
00423                                    const nsAString& matchText)
00424 {
00425     PRBool found = PR_FALSE;
00426     
00427     if (matchMethod.EqualsLiteral("isbefore") ||
00428         matchMethod.EqualsLiteral("isafter"))
00429     {
00430         PRInt64 matchDate;
00431         nsresult rv = parseDate(matchText, &matchDate);
00432         if (NS_SUCCEEDED(rv))
00433             found = dateMatches(aDate, matchMethod, matchDate);
00434     }
00435 
00436     return found;
00437 }
00438 
00439 PRBool
00440 LocalSearchDataSource::doIntMatch(nsIRDFInt *aInt,
00441                                   const nsAString& matchMethod,
00442                                   const nsString& matchText)
00443 {
00444     nsresult rv;
00445     PRBool found = PR_FALSE;
00446     
00447     PRInt32 val;
00448     rv = aInt->GetValue(&val);
00449     if (NS_FAILED(rv)) return PR_FALSE;
00450     
00451     PRInt32 error=0;
00452     PRInt32 matchVal = matchText.ToInteger(&error);
00453     if (error != 0) return PR_FALSE;
00454     
00455     if (matchMethod.EqualsLiteral("is"))
00456         found = (val == matchVal);
00457     else if (matchMethod.EqualsLiteral("isgreater"))
00458         found = (val > matchVal);
00459     else if (matchMethod.EqualsLiteral("isless"))
00460         found = (val < matchVal);
00461 
00462     return found;
00463 }
00464 
00465 NS_METHOD
00466 LocalSearchDataSource::parseDate(const nsAString& aDate,
00467                                  PRInt64 *aResult)
00468 {
00469     // date is in the form of msec since epoch, but use NSPR to
00470     // parse the time
00471     PRTime *outTime = NS_STATIC_CAST(PRTime*,aResult);
00472     PRStatus err;
00473     err = PR_ParseTimeString(NS_ConvertUCS2toUTF8(aDate).get(),
00474                              PR_FALSE, // PR_FALSE == use current timezone
00475                              outTime);
00476     NS_ENSURE_TRUE(err == 0, NS_ERROR_FAILURE);
00477     
00478     return NS_OK;
00479 }
00480 
00481 
00482 PRBool
00483 LocalSearchDataSource::dateMatches(nsIRDFDate *aDate,
00484                                    const nsAString& method,
00485                                    const PRInt64& matchDate)
00486 {
00487     PRInt64 date;
00488     aDate->GetValue(&date);
00489     PRBool matches = PR_FALSE;
00490     
00491     if (method.EqualsLiteral("isbefore"))
00492         matches = LL_CMP(date, <, matchDate);
00493     
00494     else if (method.EqualsLiteral("isafter"))
00495         matches = LL_CMP(date, >, matchDate);
00496 
00497     else if (method.EqualsLiteral("is"))
00498         matches = LL_EQ(date, matchDate);
00499 
00500     return matches;
00501 }
00502 
00503 
00504 NS_METHOD
00505 LocalSearchDataSource::parseFindURL(nsIRDFResource *u, nsISupportsArray *array)
00506 {
00507   findTokenStruct           tokens[5];
00508   nsresult rv;
00509 
00510   // build up a token list
00511   tokens[0].token = "datasource";
00512   tokens[1].token = "match";
00513   tokens[2].token = "method";
00514   tokens[3].token = "text";
00515   tokens[4].token = NULL;
00516 
00517   // parse find URI, get parameters, search in appropriate
00518   // datasource(s), return results
00519   rv = parseResourceIntoFindTokens(u, tokens);
00520   if (NS_FAILED(rv)) 
00521     return rv;
00522 
00523   nsCAutoString dsName;
00524   dsName.AssignWithConversion(tokens[0].value);
00525 
00526   nsCOMPtr<nsIRDFDataSource> datasource;
00527   rv = gRDFService->GetDataSource(dsName.get(), getter_AddRefs(datasource));
00528   if (NS_FAILED(rv)) 
00529     return rv;
00530 
00531   nsCOMPtr<nsISimpleEnumerator> cursor;
00532   rv = datasource->GetAllResources(getter_AddRefs(cursor));
00533   if (NS_FAILED(rv)) 
00534     return rv;
00535         
00536   while (PR_TRUE) {
00537     PRBool hasMore;
00538     rv = cursor->HasMoreElements(&hasMore);
00539     if (NS_FAILED(rv)) 
00540       break;
00541 
00542     if (!hasMore) 
00543       break;
00544 
00545     nsCOMPtr<nsISupports> isupports;
00546     rv = cursor->GetNext(getter_AddRefs(isupports));
00547     if (NS_FAILED(rv)) 
00548       continue;
00549 
00550     nsCOMPtr<nsIRDFResource> source(do_QueryInterface(isupports));
00551     if (!source) 
00552       continue;
00553 
00554     const char       *uri = nsnull;
00555     source->GetValueConst(&uri);
00556 
00557     if (!uri) 
00558       continue;
00559             
00560     // never match against a "find:" URI
00561     if (PL_strncmp(uri, kFindProtocol, sizeof(kFindProtocol)-1) == 0)
00562       continue;
00563 
00564     // never match against a container. Searching for folders just isn't
00565     // much of a utility, and this fixes an infinite recursion crash. (65063)
00566     PRBool isContainer = PR_FALSE;
00567 
00568     // Check to see if this source is an RDF container
00569     nsCOMPtr<nsIRDFContainerUtils> cUtils(do_GetService("@mozilla.org/rdf/container-utils;1"));
00570     if (cUtils)
00571       cUtils->IsContainer(datasource, source, &isContainer);
00572     // Check to see if this source is a pseudo-container
00573     if (!isContainer)
00574       datasource->HasArcOut(source, kNC_Child, &isContainer);
00575 
00576     if (isContainer) 
00577       continue;
00578 
00579     nsCOMPtr<nsIRDFResource> property;
00580     rv = gRDFService->GetUnicodeResource(tokens[1].value,
00581     getter_AddRefs(property));
00582 
00583     if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE) || !property)
00584       continue;
00585 
00586     nsCOMPtr<nsIRDFNode>    value;
00587     rv = datasource->GetTarget(source, property,
00588     PR_TRUE, getter_AddRefs(value));
00589     if (NS_FAILED(rv) || (rv == NS_RDF_NO_VALUE) || !value)
00590       continue;
00591 
00592     PRBool found = PR_FALSE;
00593     found = matchNode(value, tokens[2].value, tokens[3].value);
00594 
00595     if (found)
00596       array->AppendElement(source);
00597    }
00598 
00599   if (rv == NS_RDF_CURSOR_EMPTY)
00600     rv = NS_OK;
00601 
00602   return rv;
00603 }
00604 
00605 // could speed up date/integer matching signifigantly by caching the
00606 // last successful match data type (i.e. string, date, int) and trying
00607 // to QI against that first
00608 PRBool
00609 LocalSearchDataSource::matchNode(nsIRDFNode *aValue,
00610                                  const nsAString& matchMethod,
00611                                  const nsString& matchText)
00612 {
00613     nsCOMPtr<nsIRDFLiteral> literal(do_QueryInterface(aValue));
00614     if (literal)
00615         return doMatch(literal, matchMethod, matchText);
00616 
00617     nsCOMPtr<nsIRDFDate> dateLiteral(do_QueryInterface(aValue));
00618     if (dateLiteral)
00619         return doDateMatch(dateLiteral, matchMethod, matchText);
00620     
00621     nsCOMPtr<nsIRDFInt> intLiteral(do_QueryInterface(aValue));
00622     if (intLiteral)
00623         return doIntMatch(intLiteral, matchMethod, matchText);
00624 
00625     return PR_FALSE;
00626 }
00627 
00628 NS_METHOD
00629 LocalSearchDataSource::getFindResults(nsIRDFResource *source, nsISimpleEnumerator** aResult)
00630 {
00631        nsresult                    rv;
00632        nsCOMPtr<nsISupportsArray>  nameArray;
00633        rv = NS_NewISupportsArray( getter_AddRefs(nameArray) );
00634        if (NS_FAILED(rv)) return rv;
00635 
00636        rv = parseFindURL(source, nameArray);
00637        if (NS_FAILED(rv)) return rv;
00638 
00639        nsISimpleEnumerator* result = new nsArrayEnumerator(nameArray);
00640        if (! result)
00641               return(NS_ERROR_OUT_OF_MEMORY);
00642 
00643        NS_ADDREF(result);
00644        *aResult = result;
00645 
00646        return NS_OK;
00647 }
00648 
00649 
00650 
00651 NS_METHOD
00652 LocalSearchDataSource::getFindName(nsIRDFResource *source, nsIRDFLiteral** aResult)
00653 {
00654        // XXX construct find URI human-readable name
00655        *aResult = nsnull;
00656        return(NS_OK);
00657 }
00658 
00659 
00660 
00661 NS_IMETHODIMP
00662 LocalSearchDataSource::GetTargets(nsIRDFResource *source,
00663                            nsIRDFResource *property,
00664                            PRBool tv,
00665                            nsISimpleEnumerator **targets /* out */)
00666 {
00667        NS_PRECONDITION(source != nsnull, "null ptr");
00668        if (! source)
00669               return NS_ERROR_NULL_POINTER;
00670 
00671        NS_PRECONDITION(property != nsnull, "null ptr");
00672        if (! property)
00673               return NS_ERROR_NULL_POINTER;
00674 
00675        NS_PRECONDITION(targets != nsnull, "null ptr");
00676        if (! targets)
00677               return NS_ERROR_NULL_POINTER;
00678 
00679        nsresult             rv = NS_ERROR_FAILURE;
00680 
00681        // we only have positive assertions in the find data source.
00682        if (! tv)
00683               return rv;
00684 
00685        if (isFindURI(source))
00686        {
00687               if (property == kNC_Child)
00688               {
00689                      return getFindResults(source, targets);
00690               }
00691               else if (property == kNC_Name)
00692               {
00693                      nsCOMPtr<nsIRDFLiteral>     name;
00694                      rv = getFindName(source, getter_AddRefs(name));
00695                      if (NS_FAILED(rv)) return rv;
00696 
00697                      nsISimpleEnumerator* result =
00698                      new nsSingletonEnumerator(name);
00699 
00700                      if (! result)
00701                             return NS_ERROR_OUT_OF_MEMORY;
00702 
00703                      NS_ADDREF(result);
00704                      *targets = result;
00705                      return NS_OK;
00706               }
00707               else if (property == kRDF_type)
00708               {
00709                      const  char   *uri = nsnull;
00710                      rv = kNC_FindObject->GetValueConst( &uri );
00711                      if (NS_FAILED(rv)) return rv;
00712 
00713                      nsAutoString  url; url.AssignWithConversion(uri);
00714                      nsIRDFLiteral *literal;
00715                      rv = gRDFService->GetLiteral(url.get(), &literal);
00716                      if (NS_FAILED(rv)) return rv;
00717 
00718                      nsISimpleEnumerator* result = new nsSingletonEnumerator(literal);
00719 
00720                      NS_RELEASE(literal);
00721 
00722                      if (! result)
00723                             return NS_ERROR_OUT_OF_MEMORY;
00724 
00725                      NS_ADDREF(result);
00726                      *targets = result;
00727                      return NS_OK;
00728               }
00729               else if (property == kNC_pulse)
00730               {
00731                      nsAutoString  pulse(NS_LITERAL_STRING("15"));
00732                      nsIRDFLiteral *pulseLiteral;
00733                      rv = gRDFService->GetLiteral(pulse.get(), &pulseLiteral);
00734                      if (NS_FAILED(rv)) return rv;
00735 
00736                      nsISimpleEnumerator* result = new nsSingletonEnumerator(pulseLiteral);
00737 
00738                      NS_RELEASE(pulseLiteral);
00739 
00740                      if (! result)
00741                             return NS_ERROR_OUT_OF_MEMORY;
00742 
00743                      NS_ADDREF(result);
00744                      *targets = result;
00745                      return NS_OK;
00746               }
00747        }
00748 
00749        return NS_NewEmptyEnumerator(targets);
00750 }
00751 
00752 
00753 
00754 NS_IMETHODIMP
00755 LocalSearchDataSource::Assert(nsIRDFResource *source,
00756                        nsIRDFResource *property,
00757                        nsIRDFNode *target,
00758                        PRBool tv)
00759 {
00760        return NS_RDF_ASSERTION_REJECTED;
00761 }
00762 
00763 
00764 
00765 NS_IMETHODIMP
00766 LocalSearchDataSource::Unassert(nsIRDFResource *source,
00767                          nsIRDFResource *property,
00768                          nsIRDFNode *target)
00769 {
00770        return NS_RDF_ASSERTION_REJECTED;
00771 }
00772 
00773 
00774 
00775 NS_IMETHODIMP
00776 LocalSearchDataSource::Change(nsIRDFResource* aSource,
00777                        nsIRDFResource* aProperty,
00778                        nsIRDFNode* aOldTarget,
00779                        nsIRDFNode* aNewTarget)
00780 {
00781        return NS_RDF_ASSERTION_REJECTED;
00782 }
00783 
00784 
00785 
00786 NS_IMETHODIMP
00787 LocalSearchDataSource::Move(nsIRDFResource* aOldSource,
00788                      nsIRDFResource* aNewSource,
00789                      nsIRDFResource* aProperty,
00790                      nsIRDFNode* aTarget)
00791 {
00792        return NS_RDF_ASSERTION_REJECTED;
00793 }
00794 
00795 
00796 
00797 NS_IMETHODIMP
00798 LocalSearchDataSource::HasAssertion(nsIRDFResource *source,
00799                              nsIRDFResource *property,
00800                              nsIRDFNode *target,
00801                              PRBool tv,
00802                              PRBool *hasAssertion /* out */)
00803 {
00804        NS_PRECONDITION(source != nsnull, "null ptr");
00805        if (! source)
00806               return NS_ERROR_NULL_POINTER;
00807 
00808        NS_PRECONDITION(property != nsnull, "null ptr");
00809        if (! property)
00810               return NS_ERROR_NULL_POINTER;
00811 
00812        NS_PRECONDITION(target != nsnull, "null ptr");
00813        if (! target)
00814               return NS_ERROR_NULL_POINTER;
00815 
00816        NS_PRECONDITION(hasAssertion != nsnull, "null ptr");
00817        if (! hasAssertion)
00818               return NS_ERROR_NULL_POINTER;
00819 
00820        nsresult             rv = NS_OK;
00821 
00822        *hasAssertion = PR_FALSE;
00823 
00824        // we only have positive assertions in the find data source.
00825        if (! tv)
00826               return rv;
00827 
00828        if (isFindURI(source))
00829        {
00830               if (property == kRDF_type)
00831               {
00832                      if ((nsIRDFResource *)target == kRDF_type)
00833                      {
00834                             *hasAssertion = PR_TRUE;
00835                      }
00836               }
00837        }
00838        return (rv);
00839 }
00840 
00841 NS_IMETHODIMP 
00842 LocalSearchDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
00843 {
00844     *result = PR_FALSE;
00845     return NS_OK;
00846 }
00847 
00848 NS_IMETHODIMP 
00849 LocalSearchDataSource::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, PRBool *result)
00850 {
00851     NS_PRECONDITION(source != nsnull, "null ptr");
00852     if (! source)
00853         return NS_ERROR_NULL_POINTER;
00854 
00855     if ((aArc == kNC_Child ||
00856          aArc == kNC_pulse)) {
00857         *result = isFindURI(source);
00858     }
00859     else {
00860         *result = PR_FALSE;
00861     }
00862     return NS_OK;
00863 }
00864 
00865 NS_IMETHODIMP
00866 LocalSearchDataSource::ArcLabelsIn(nsIRDFNode *node,
00867                             nsISimpleEnumerator ** labels /* out */)
00868 {
00869        NS_NOTYETIMPLEMENTED("write me");
00870        return NS_ERROR_NOT_IMPLEMENTED;
00871 }
00872 
00873 
00874 
00875 NS_IMETHODIMP
00876 LocalSearchDataSource::ArcLabelsOut(nsIRDFResource *source,
00877                              nsISimpleEnumerator **labels /* out */)
00878 {
00879        NS_PRECONDITION(source != nsnull, "null ptr");
00880        if (! source)
00881               return NS_ERROR_NULL_POINTER;
00882 
00883        NS_PRECONDITION(labels != nsnull, "null ptr");
00884        if (! labels)
00885               return NS_ERROR_NULL_POINTER;
00886 
00887        nsresult             rv;
00888 
00889        if (isFindURI(source))
00890        {
00891               nsCOMPtr<nsISupportsArray> array;
00892               rv = NS_NewISupportsArray( getter_AddRefs(array) );
00893               if (NS_FAILED(rv)) return rv;
00894 
00895               array->AppendElement(kNC_Child);
00896               array->AppendElement(kNC_pulse);
00897 
00898               nsISimpleEnumerator* result = new nsArrayEnumerator(array);
00899               if (! result)
00900                      return NS_ERROR_OUT_OF_MEMORY;
00901 
00902               NS_ADDREF(result);
00903               *labels = result;
00904               return(NS_OK);
00905        }
00906        return(NS_NewEmptyEnumerator(labels));
00907 }
00908 
00909 
00910 
00911 NS_IMETHODIMP
00912 LocalSearchDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
00913 {
00914        NS_NOTYETIMPLEMENTED("sorry!");
00915        return NS_ERROR_NOT_IMPLEMENTED;
00916 }
00917 
00918 
00919 
00920 NS_IMETHODIMP
00921 LocalSearchDataSource::AddObserver(nsIRDFObserver *n)
00922 {
00923        NS_PRECONDITION(n != nsnull, "null ptr");
00924        if (! n)
00925               return NS_ERROR_NULL_POINTER;
00926 
00927        if (! mObservers)
00928        {
00929               nsresult      rv;
00930               rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
00931               if (NS_FAILED(rv)) return rv;
00932        }
00933        return mObservers->AppendElement(n) ? NS_OK : NS_ERROR_FAILURE;
00934 }
00935 
00936 
00937 
00938 NS_IMETHODIMP
00939 LocalSearchDataSource::RemoveObserver(nsIRDFObserver *n)
00940 {
00941        NS_PRECONDITION(n != nsnull, "null ptr");
00942        if (! n)
00943               return NS_ERROR_NULL_POINTER;
00944 
00945        if (! mObservers)
00946               return(NS_OK);
00947 
00948 #ifdef DEBUG
00949        PRBool ok =
00950 #endif
00951        mObservers->RemoveElement(n);
00952 
00953        NS_ASSERTION(ok, "observer not present");
00954 
00955        return(NS_OK);
00956 }
00957 
00958 
00959 
00960 NS_IMETHODIMP
00961 LocalSearchDataSource::GetAllCmds(nsIRDFResource* source, nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
00962 {
00963        return(NS_NewEmptyEnumerator(commands));
00964 }
00965 
00966 
00967 
00968 NS_IMETHODIMP
00969 LocalSearchDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00970                             nsIRDFResource*   aCommand,
00971                             nsISupportsArray/*<nsIRDFResource>*/* aArguments,
00972                                 PRBool* aResult)
00973 {
00974        return(NS_ERROR_NOT_IMPLEMENTED);
00975 }
00976 
00977 
00978 
00979 NS_IMETHODIMP
00980 LocalSearchDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
00981                             nsIRDFResource*   aCommand,
00982                             nsISupportsArray/*<nsIRDFResource>*/* aArguments)
00983 {
00984        return(NS_ERROR_NOT_IMPLEMENTED);
00985 }
00986 
00987 
00988 
00989 NS_IMETHODIMP
00990 LocalSearchDataSource::BeginUpdateBatch()
00991 {
00992        return NS_OK;
00993 }
00994 
00995 
00996 
00997 NS_IMETHODIMP
00998 LocalSearchDataSource::EndUpdateBatch()
00999 {
01000        return NS_OK;
01001 }