home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / modules / rdf / src / mcf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  21.4 KB  |  877 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /* 
  20.    This file (which should probably be called rdf.c) implements the
  21.    core rdf query mechanism.
  22.    For more information on this file, contact rjc or guha 
  23.    For more information on RDF, look at the RDF section of www.mozilla.org
  24. */
  25.  
  26. #include "mcf.h"
  27. #include "columns.h"
  28. #include "fs2rdf.h"
  29. #include "hist2rdf.h"
  30. #include "nlcstore.h"
  31. #include "remstore.h"
  32. #include "es2mcf.h"
  33. #include "pm2rdf.h"
  34. #include "scook.h"
  35.  
  36.  
  37.     /* globals */
  38. RDFL        gAllDBs = 0;
  39.  
  40.  
  41.  
  42. RDFT
  43. getTranslator (char* url)
  44. {
  45.   if (startsWith(url, "rdf:localStore")) {
  46.     return MakeLocalStore(url);
  47.   } else if (startsWith(url, "rdf:remoteStore")) {
  48.     return MakeRemoteStore(url);
  49.   } else if (startsWith(url, "rdf:history")) {
  50.     return MakeHistoryStore(url);
  51.   } else if (startsWith(url, "rdf:esftp")) {
  52.     return MakeESFTPStore(url);
  53.     /*  } else if (startsWith(url, "rdf:mail")) {
  54.     return MakeMailStore(url); */
  55.   } else if (startsWith(url, "rdf:lfs")) {
  56.     return MakeLFSStore(url);
  57.   } else if (endsWith(".rdf", url) || (endsWith(".mcf", url))) {
  58.     return MakeFileDB(url);
  59.   } else if (startsWith("rdf:columns", url)) {
  60.     return MakeColumnStore (url);
  61.   } else if (startsWith("rdf:ht", url) || startsWith("rdf:scook", url)) {
  62.     return MakeSCookDB(url);
  63.   } else  return NULL;
  64. }
  65.  
  66.  
  67.  
  68. PR_PUBLIC_API(RDF)
  69. RDF_GetDB (const char** dataSources)
  70. {
  71.   uint16 n = 0;
  72.   uint16 m = 0;
  73.   char* next ;
  74.   RDF r = (RDF) getMem(sizeof(struct RDF_DBStruct)) ;
  75.   RDFL nrl = (RDFL)getMem(sizeof(struct RDF_ListStruct));
  76.   while (*(dataSources + n++)) {} 
  77.   r->translators = (RDFT*)getMem((n-1) * sizeof(RDFT));
  78.   n = 0;
  79.   while (next = (char*) *(dataSources + n)) {
  80.     RDFL rl = (RDFL)getMem(sizeof(struct RDF_ListStruct));
  81.     r->translators[m] = getTranslator(next);
  82.     if (r->translators[m] != NULL) { 
  83.         rl->rdf = r;
  84.         rl->next = r->translators[m]->rdf;
  85.         r->translators[m]->rdf = rl;
  86.         m++;
  87.     } else {
  88.         freeMem(rl);
  89.     }
  90.     n++;
  91.   }
  92.   r->numTranslators = m;
  93.   nrl->rdf = r;
  94.   nrl->next = gAllDBs;
  95.   gAllDBs = nrl;
  96.   return r;
  97. }
  98.  
  99.  
  100.  
  101. RDFL
  102. deleteFromRDFList (RDFL xrl, RDF db)
  103. {
  104.   RDFL rl = xrl;
  105.   RDFL prev = rl;
  106.   while (rl) {
  107.       if (rl->rdf == db) {
  108.         if (prev == rl) {
  109.           RDFL ans = rl->next;
  110.           freeMem(rl);
  111.           return ans;
  112.         } else {
  113.           prev->next = rl->next;
  114.           freeMem(rl);
  115.           return xrl;
  116.         }
  117.       }
  118.       prev = rl;
  119.       rl   = rl->next;
  120.   }
  121.   return xrl;
  122. }
  123.  
  124.  
  125.  
  126. void
  127. disposeAllDBs ()
  128. {
  129.   while (gAllDBs) {
  130.     RDF_ReleaseDB(gAllDBs->rdf);
  131.   }
  132. }
  133.  
  134.  
  135.  
  136. PR_PUBLIC_API(RDF_Error) 
  137. RDF_ReleaseDB(RDF rdf)
  138. {
  139.   if (rdf != NULL) {
  140.     uint16 n = 0;
  141.     uint16 size = rdf->numTranslators;
  142.     while (n < size) {
  143.       RDFL rlx = (*((RDFT*)rdf->translators + n))->rdf;
  144.       (*((RDFT*)rdf->translators + n))->rdf =  deleteFromRDFList(rlx, rdf); 
  145.       callExitRoutine(n, rdf);
  146.       n++;
  147.     }
  148.     gAllDBs = deleteFromRDFList(gAllDBs, rdf);
  149.   }
  150.   freeMem(rdf);
  151.   return noRDFErr;
  152. }
  153.  
  154.  
  155.  
  156. RDF_Resource
  157. addDep (RDF db, RDF_Resource u)
  158. {
  159.  
  160.   if (db) {
  161.     RDFL rl = u->rdf;
  162.     while (rl) {
  163.       if (rl->rdf == db) return u;
  164.       rl = rl->next;
  165.     }
  166.     rl = (RDFL) getMem(sizeof(struct RDF_ListStruct));
  167.     rl->rdf = db;
  168.     rl->next = u->rdf;
  169.     u->rdf = rl;
  170.     return u;
  171.   }
  172.   return u;
  173. }
  174.  
  175.  
  176.  
  177. PRBool
  178. rdfassert(RDF rdf, RDF_Resource u, RDF_Resource  s, void* value, 
  179.           RDF_ValueType type,  PRBool tv)
  180. {
  181.    uint16 size =  rdf->numTranslators;
  182.    int16 n = size -1;
  183.    
  184.    /* XXX - what happens here if there is no local store? */     
  185.    if ((size > 1) && (callHasAssertions(0, rdf, u, s, value, type, (!tv)))) {
  186.      setLockedp(u, 1);
  187.      callUnassert(0, rdf, u, s, value, type); 
  188.      setLockedp(u, 0);
  189.      if (RDF_HasAssertion(rdf, u, s, value, type, tv)) return 1;
  190.    }
  191.    while (n > -1) {
  192.      if (callAssert(n, rdf, u, s, value, type, tv)) return 1; 
  193.      n--; 
  194.    }  
  195.    return 0;
  196. }
  197.  
  198.  
  199.  
  200. PR_PUBLIC_API(PRBool)
  201. RDF_Assert (RDF rdf, RDF_Resource u, RDF_Resource  s, void* value, RDF_ValueType type)
  202. {
  203.     return rdfassert(rdf, u, s, value, type, 1);
  204. }
  205.  
  206.  
  207.  
  208. PR_PUBLIC_API(PRBool)
  209. RDF_AssertFalse (RDF rdf, RDF_Resource u, RDF_Resource  s, void* value, RDF_ValueType type)
  210. {
  211.     return rdfassert(rdf, u, s, value, type, 0);
  212. }
  213.  
  214.  
  215.  
  216. PR_PUBLIC_API(PRBool)
  217. RDF_Unassert (RDF rdf, RDF_Resource u, RDF_Resource s, void* value, RDF_ValueType type)
  218. {
  219.   PRBool allok = 1;
  220.   uint16 size =  rdf->numTranslators;
  221.   uint16 n = 0;
  222.   
  223.   setLockedp(u, 1);
  224.   while (allok && (n < size)) {
  225.     if (callHasAssertions(n, rdf, u, s, value, type, 1)) {
  226.       allok = callUnassert(n, rdf, u, s, value, type);
  227.     }
  228.     n++;
  229.   }
  230.   if (!allok) allok = callAssert(0, rdf, u, s, value, type, 0); 
  231.   setLockedp(u, 0);
  232.   return allok;
  233. }
  234.  
  235.  
  236.  
  237. PRBool
  238. containerIDp(char* id)
  239. {
  240.   return (endsWith(".rdf", id) || (endsWith(".mco", id)) || (endsWith(".mcf", id)) || 
  241.            strstr(id, ".rdf#"));
  242. }
  243.  
  244.  
  245.  
  246. char *
  247. makeNewID ()
  248. {
  249.  
  250.   PRTime tm = PR_Now();
  251.  
  252. #ifndef HAVE_LONG_LONG
  253.   double doubletm;
  254. #endif /* !HAVE_LONG_LONG */
  255.  
  256.   char* id = (char*)getMem(ID_BUF_SIZE);
  257.  
  258.  #ifdef HAVE_LONG_LONG
  259.   PR_snprintf(id, ID_BUF_SIZE, "%u", (double)tm);
  260.  #else
  261.   LL_L2D(doubletm, tm);
  262.   PR_snprintf(id, ID_BUF_SIZE, "%d", doubletm);
  263.  #endif /* HAVE_LONG_LONG */
  264.  
  265.   /* prevent collisions by checking hash. */
  266.   while (PL_HashTableLookup(resourceHash, id) != NULL) {
  267.      #ifdef HAVE_LONG_LONG
  268.       tm = tm + (PR_MSEC_PER_SEC * 60); /* fix me - not sure what the increment should be */
  269.       PR_snprintf(id, ID_BUF_SIZE, "%u", (double)tm);
  270.     #else
  271.       int64 incr;
  272.       LL_I2L(incr, (PR_MSEC_PER_SEC * 60));
  273.       LL_ADD(tm, tm, incr);
  274.       LL_L2D(doubletm, tm);
  275.       PR_snprintf(id, ID_BUF_SIZE, "%d", doubletm);
  276.     #endif /* HAVE_LONG_LONG */
  277.   }
  278.  
  279.   return id;
  280. }
  281.  
  282.  
  283.  
  284. PRBool
  285. iscontainerp (RDF_Resource u)
  286. {
  287.   char* id = resourceID(u);
  288.   if (containerIDp(id)) {
  289.     return 1;
  290.   } else if (startsWith("file:", id)) {
  291.     return fileDirectoryp(u);
  292.   } else if (startsWith("ftp:", id) && (endsWith("/", id))) {
  293.     return 1;
  294.   } else if (startsWith("cache:container", id)) {
  295.     return 1;
  296.   } else  return 0; 
  297.  
  298.  
  299.  
  300. RDF_BT
  301. resourceTypeFromID (char* id)
  302. {
  303.   if (endsWith(".rdf", id) || (strstr(id, ".rdf#"))) {
  304.     return RDF_RT;
  305.   } else if (endsWith(".mcf", id) || (strstr(id, ".mcf#"))) {
  306.     return RDF_RT;
  307.   } else if (endsWith(".mco", id)) {
  308.     return RDF_RT;
  309.   } else if (startsWith("file:", id) || (startsWith("NC:LocalFiles", id))) {
  310.     return LFS_RT;
  311.   } else if (startsWith("nes:", id)) {
  312.     return ES_RT;
  313.   } else if (startsWith("ftp:", id)) {
  314.     return FTP_RT;
  315.   } else if (startsWith("cache:", id)) {
  316.     return CACHE_RT;
  317.   } else return 0;
  318. }
  319.  
  320.  
  321.  
  322. PR_PUBLIC_API(RDF_Resource)
  323. RDF_GetResource (RDF db, char* id, PRBool createp)
  324. {
  325.   char* nid;
  326.   RDF_Resource existing;
  327.   if (id != NULL) {
  328.     existing = (RDF_Resource)PL_HashTableLookup(resourceHash, id);
  329.     if (existing != null) return addDep(db, existing);
  330.     if (!createp) {
  331.       return null;
  332.     } else {
  333.       nid = copyString(id);
  334.     }
  335.   } else if (createp != false) {
  336.     nid = makeNewID();
  337.   }
  338.   existing = (RDF_Resource)getMem(sizeof(struct RDF_ResourceStruct)); 
  339.   existing->url = nid;
  340.   PL_HashTableAdd(resourceHash, nid, existing);
  341.   setResourceType(existing, resourceTypeFromID(nid));
  342.   setContainerp(existing, iscontainerp(existing));
  343.   return addDep(db, existing);
  344.   
  345. }
  346.  
  347.  
  348.   
  349. PR_PUBLIC_API (RDF_Error)
  350. RDF_DeleteAllArcs (RDF rdf, RDF_Resource u)
  351. {
  352.   Assertion as, next;
  353.   /*  if (u->locked) return -1; */
  354.   as = u->rarg1;
  355.   while (as != NULL) {
  356.     next = as->next;
  357.     remoteStoreRemove(gRemoteStore, as->u, as->s, as->value, as->type);
  358.     as = next;
  359.   }
  360.   as = u->rarg2;
  361.   while (as != NULL) {
  362.     next = as->invNext;
  363.     remoteStoreRemove(gRemoteStore, as->u, as->s, as->value, as->type);
  364.     as = next;
  365.   }
  366. #ifdef DBMTEST
  367.  nlclStoreKill(gLocalStore, u);
  368. #endif
  369.   return 0;
  370. }
  371.  
  372.  
  373.  
  374. PR_PUBLIC_API(PRBool)
  375. RDF_HasAssertion (RDF rdf, RDF_Resource u, RDF_Resource s, 
  376.              void* v, RDF_ValueType type, PRBool tv)
  377. {
  378.   uint16 size = rdf->numTranslators;
  379.   uint16 n = 0;
  380.   if (callHasAssertions(0, rdf, u, s, v, type, !tv)) return 0;
  381.   while (n < size) {
  382.     if (callHasAssertions(n, rdf, u, s, v, type, tv)) return 1;
  383.     n++;
  384.   }
  385.   return 0; 
  386. }
  387.  
  388.  
  389.  
  390. PR_PUBLIC_API(void *)
  391. RDF_GetSlotValue (RDF rdf, RDF_Resource u, RDF_Resource s, 
  392.             RDF_ValueType type, PRBool inversep, PRBool tv)
  393. {
  394.   uint16 size =  rdf->numTranslators; 
  395.   uint16 n = 0;
  396.   if (s == gWebData->RDF_URL && tv && !inversep && type == RDF_STRING_TYPE) 
  397.     return  copyString(resourceID(u));         
  398.   while (n < size) {
  399.     void*  ans = callGetSlotValue(n, rdf, u, s, type, inversep, tv);
  400.     if ((ans != NULL) && ((n == 0)||(!callHasAssertions(0, rdf, u, s, ans, type, !tv))))
  401.     if (type == RDF_RESOURCE_TYPE) {
  402.       return addDep(rdf, ans) ;
  403.       } else return ans;
  404.     n++;
  405.   }
  406.   if (s == gCoreVocab->RDF_name && tv && !inversep && type == RDF_STRING_TYPE) 
  407.     return makeResourceName(u);
  408.   return NULL; 
  409. }
  410.  
  411.  
  412.  
  413. RDF_Cursor
  414. getSlotValues (RDF rdf, RDF_Resource u, RDF_Resource s, 
  415.               RDF_ValueType type, PRBool inversep, PRBool tv)
  416. {
  417.   RDF_Cursor c = (RDF_Cursor) getMem(sizeof(struct RDF_CursorStruct));
  418.   if (c == NULL)    return(NULL);
  419.   c->u = u;
  420.   c->s = s;
  421.   c->queryType =  RDF_GET_SLOT_VALUES_QUERY;
  422.   c->tv = tv;
  423.   c->inversep = inversep;
  424.   c->type = type;
  425.   c->count = -1;
  426.   c->rdf = rdf;
  427.   c->current = NULL;
  428.   while ((c->count < rdf->numTranslators-1) && (!c->current)) {
  429.     c->count++;
  430.     c->current = callGetSlotValues(c->count, rdf, u, s, type, inversep, tv);
  431.   }
  432.   if (!c->current) {
  433.     freeMem(c);
  434.     return NULL;
  435.   } else {
  436.     return c;
  437.   }
  438. }
  439.  
  440.  
  441.  
  442. PR_PUBLIC_API(RDF_Cursor)
  443. RDF_GetTargets (RDF rdfDB, RDF_Resource source, RDF_Resource arcLabel, 
  444.                       RDF_ValueType targetType,  PRBool tv)
  445. {
  446.     return getSlotValues(rdfDB, source, arcLabel, targetType, 0, tv);
  447. }
  448.  
  449.  
  450.  
  451. PR_PUBLIC_API(RDF_Cursor)
  452. RDF_GetSources (RDF rdfDB, RDF_Resource target, RDF_Resource arcLabel, 
  453.                       RDF_ValueType sourceType,  PRBool tv)
  454. {
  455.   if (sourceType != RDF_RESOURCE_TYPE) return NULL;
  456.   return getSlotValues(rdfDB, target, arcLabel, sourceType, 1, tv);
  457. }
  458.  
  459.  
  460.  
  461. PR_PUBLIC_API(RDF_ValueType)
  462. RDF_CursorValueType(RDF_Cursor c)
  463. {
  464.   if (c == NULL) {
  465.     return 0;
  466.   } else {
  467.     return c->type;
  468.   }
  469. }
  470.  
  471.  
  472.  
  473. PR_PUBLIC_API(char*)
  474. RDF_ValueDataSource(RDF_Cursor c)
  475. {
  476.   if (c == NULL) {
  477.     return NULL;
  478.   } else {
  479.     RDF rdf = c->rdf;
  480.     RDFT rdft;
  481.     if (rdf == NULL) return NULL;
  482.     rdft = rdf->translators[c->count];
  483.     if (rdft) {
  484.       return rdft->url;
  485.     } else {
  486.       return NULL;
  487.     }
  488.   }
  489. }
  490.  
  491.  
  492.  
  493. PR_PUBLIC_API(RDF_Cursor)
  494. RDF_ArcLabelsOut (RDF rdfDB, RDF_Resource u)
  495. {
  496.   RDF_Cursor c = (RDF_Cursor) getMem(sizeof(struct RDF_CursorStruct));
  497.   if (c == NULL)   return(NULL);
  498.   c->u = u;
  499.   c->queryType =  RDF_ARC_LABELS_OUT_QUERY;
  500.   c->type = RDF_RESOURCE_TYPE;
  501.   c->count = -1;
  502.   c->rdf = rdfDB;
  503.   c->current = NULL;
  504.   while ((c->count < rdfDB->numTranslators-1) && (!c->current)) {
  505.     c->count++;
  506.     c->current = callArcLabelsOut(c->count, rdfDB, u);
  507.   } 
  508.   if (!c->current) {
  509.     freeMem(c);
  510.     return NULL;
  511.   } else {
  512.     return c;
  513.   }
  514. }
  515.  
  516.  
  517.  
  518. PR_PUBLIC_API(RDF_Cursor)
  519. RDF_ArcLabelsIn (RDF rdfDB, RDF_Resource u)
  520. {
  521.   RDF_Cursor c = (RDF_Cursor) getMem(sizeof(struct RDF_CursorStruct));
  522.   if (c == NULL)   return(NULL);
  523.   c->u = u;
  524.   c->queryType =  RDF_ARC_LABELS_IN_QUERY;
  525.   c->type = RDF_RESOURCE_TYPE;
  526.   c->count = -1;
  527.   c->rdf = rdfDB;
  528.   c->current = NULL;
  529.   while ((c->count < rdfDB->numTranslators-1) && (!c->current)) {
  530.     c->count++;
  531.     c->current = callArcLabelsIn(c->count, rdfDB, u);
  532.   }
  533.   if (!c->current) {
  534.     freeMem(c);
  535.     return NULL;
  536.   } else {
  537.     return c;
  538.   }
  539. }
  540.  
  541.  
  542.  
  543. PR_PUBLIC_API(void *)
  544. RDF_NextValue (RDF_Cursor c)
  545. {
  546.   void* ans;
  547.   RDF rdf;  
  548.   if (c == NULL) return NULL;
  549.   if (c->queryType == RDF_FIND_QUERY) return nextFindValue(c);
  550.   rdf =  c->rdf;
  551.   ans = (*rdf->translators[c->count]->nextValue)(rdf->translators[c->count], c->current);
  552.   while (ans != NULL) {
  553.     if (c->count == 0) return addDep(c->rdf, ans);
  554.     if (((!c->inversep) && 
  555.     (!(callHasAssertions(0, rdf, c->u, c->s, ans, c->type, !c->tv)))) ||
  556.     ((c->inversep) && 
  557.      (!(callHasAssertions(0, rdf, (RDF_Resource)ans, c->s, c->u, 
  558.                   c->type, !c->tv))))) {
  559.       if (c->type == RDF_RESOURCE_TYPE) {
  560.     return addDep(c->rdf, (RDF_Resource)ans);
  561.       } else return ans;
  562.     }
  563.     ans = (*rdf->translators[c->count]->nextValue)(rdf->translators[c->count], c->current);
  564.   }
  565.   (*rdf->translators[c->count]->disposeCursor)(rdf->translators[c->count], c->current);
  566.   c->current = NULL;
  567.   while ((c->count < rdf->numTranslators - 1) && (!c->current)) {
  568.     c->count++;
  569.     c->current = callGetSlotValues(c->count,rdf, c->u, c->s, c->type, 
  570.                    c->inversep, c->tv);
  571.   }
  572.   if (c->current == NULL) return NULL;
  573.   return RDF_NextValue(c);
  574. }
  575.  
  576.  
  577.  
  578. void 
  579. disposeResourceInt (RDF rdf, RDF_Resource u)
  580. {
  581.   uint16 size = rdf->numTranslators;
  582.   uint16 n = 0;
  583.   PRBool ok = 1;
  584.   while (n < size && ok) {
  585.     ok = (callDisposeResource(n, rdf, u));
  586.     n++;
  587.   } 
  588.   if (ok && (!lockedp(u))) possiblyGCResource(u);
  589. }
  590.     
  591.   
  592.  
  593. PR_PUBLIC_API(RDF_Error) 
  594. RDF_ReleaseResource (RDF db, RDF_Resource u)
  595. {
  596.   if (db && u) {    
  597.     
  598.     u->rdf = deleteFromRDFList(u->rdf, db);
  599.     if (u->rdf == NULL)  disposeResourceInt(db, u);
  600.   }
  601.   return 0;
  602. }
  603.  
  604.  
  605.  
  606. PR_PUBLIC_API(RDF_Error)
  607. RDF_DisposeCursor (RDF_Cursor c)
  608. {
  609.   if ((c != NULL) && (c->queryType == RDF_FIND_QUERY) && (c->pdata)) freeMem(c->pdata);
  610.   if (c != NULL) freeMem(c);
  611.   return 0;
  612. }
  613.  
  614.  
  615.  
  616. PRIntn
  617. findEnumerator (PLHashEntry *he, PRIntn i, void *arg)
  618. {
  619.   RDF_Cursor c = (RDF_Cursor) arg;
  620.   RDF_Resource u = (RDF_Resource)he->value;
  621.   if (itemMatchesFind(c->rdf, u, c->s, c->value, c->type)) {
  622.     c->count++;
  623.     if (c->size <= c->count) {
  624.       RDF_Resource* newBlock = getMem(c->size+5);
  625.       if (newBlock == NULL) return  HT_ENUMERATE_STOP;
  626.       if (c->size > 0) {
  627.     memcpy(newBlock, c->pdata, c->size * sizeof(RDF_Resource*));
  628.     freeMem(c->pdata);
  629.       }
  630.       c->pdata = newBlock;
  631.     }
  632.     *((RDF_Resource*)c->pdata + c->count) = u;
  633.   }
  634.   return  HT_ENUMERATE_NEXT;
  635. }
  636.  
  637.  
  638.  
  639. PR_PUBLIC_API(RDF_Cursor)
  640. RDF_Find (RDF_Resource s, void* v, RDF_ValueType type)
  641. {
  642.   RDF_Cursor c = (RDF_Cursor) getMem(sizeof(struct RDF_CursorStruct));
  643.   c->s = s;
  644.   c->value = v;
  645.   c->type = type;
  646.   c->queryType =  RDF_FIND_QUERY;
  647.   c->count = 0;
  648.   PL_HashTableEnumerateEntries(resourceHash, findEnumerator, c);
  649.   c->count = 0;
  650.   return c;
  651. }
  652.  
  653.  
  654.  
  655. PRBool
  656. itemMatchesFind (RDF r, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type)
  657. {
  658.   RDF_Cursor c = RDF_GetTargets(r, u, s, type, 1);
  659.   void* val;
  660.   while (val = RDF_NextValue(c)) {
  661.     PRBool ok = 0;
  662.     if (type == RDF_RESOURCE_TYPE) {
  663.       ok = (u == v);
  664.     } else if (type == RDF_STRING_TYPE) {
  665.       ok = (strstr(val, v) != NULL);
  666.     }
  667.     if (ok) {
  668.       RDF_DisposeCursor(c);
  669.       return 1;
  670.     }
  671.   }
  672.   return 0;
  673. }
  674.  
  675.  
  676.  
  677. RDF_Resource
  678. nextFindValue (RDF_Cursor c)
  679. {
  680.   if (c->count < c->size && (*((RDF_Resource*)c->pdata + c->count) != NULL)) {
  681.     RDF_Resource ans = (RDF_Resource)*((RDF_Resource*)c->pdata + c->count);
  682.     c->count++;
  683.     return ans;
  684.   } else   return NULL;
  685. }
  686.  
  687.  
  688.  
  689. void
  690. possiblyGCResource (RDF_Resource u)
  691. {
  692.   if ((nullp(u->rarg1)) && (nullp(u->rarg2))) {
  693.     PL_HashTableRemove(resourceHash,  resourceID(u));
  694.     freeMem(u->url);
  695.     freeMem(u);  
  696.   }
  697. }
  698.  
  699.  
  700.  
  701. PR_PUBLIC_API(RDF_Notification)
  702. RDF_AddNotifiable (RDF rdfDB, RDF_NotificationProc callBack, 
  703.                          RDF_Event ev, void* pdata)
  704. {
  705.   RDF_Notification ns = (RDF_Notification)getMem(sizeof(struct RDF_NotificationStruct));
  706.   RDF_Event        nev = (RDF_Event)getMem(sizeof(struct RDF_EventStruct));
  707.   memcpy((char*)nev, ev, sizeof(struct RDF_EventStruct));
  708.   ns->theEvent = nev;
  709.   ns->notifFunction = callBack;
  710.   ns->pdata = pdata;
  711.   ns->next = rdfDB->notifs;
  712.   rdfDB->notifs = ns;
  713.   ns->rdf = rdfDB;
  714.   return ns;
  715. }
  716.  
  717.  
  718.  
  719. PR_PUBLIC_API(RDF_Error)
  720. RDF_DeleteNotifiable (RDF_Notification ns)
  721. {
  722.   RDF rdf = ns->rdf;
  723.   RDF_Notification pr = rdf->notifs;
  724.   RDF_Notification not;
  725.   if (pr == ns) {
  726.     rdf->notifs = pr->next; 
  727.   } else {
  728.     for (not = rdf->notifs; (not != NULL) ; not = not->next) {
  729.       if (ns == not) {
  730.     pr->next = not->next; 
  731.     return 0;
  732.       }
  733.       pr = not;
  734.     }
  735.   }
  736.   freeMem(ns->theEvent);
  737.   freeMem(ns);
  738.   return 0;
  739. }
  740.  
  741.  
  742.  
  743. void
  744. assertNotify (RDF rdf, RDF_Notification not, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv, char* ds)
  745.  {
  746.   RDF_Event nev = not->theEvent;
  747.   RDF_AssertEvent ev = &(not->theEvent->event.assert);
  748.   PRBool opTypeFixed = not->theEvent->eventType;
  749.   PRBool uFixed      = (ev->u != NULL);
  750.   PRBool sFixed        = (ev->s != NULL);
  751.   PRBool vFixed        = (ev->v != NULL);
  752.   RDF_EventType  oldEventType   = not->theEvent->eventType;
  753.   if ((!opTypeFixed ||(not->theEvent->eventType & RDF_ASSERT_NOTIFY)) &&
  754.       (!uFixed      || (ev->u      == u))      &&
  755.       (!vFixed    || (ev->v      == v))       &&
  756.       (!sFixed      || (ev->s      == s))) {
  757.     /*   if     (callHasAssertions(0, rdf, u, s, v, type, !tv)) return; */
  758.     nev->eventType = RDF_ASSERT_NOTIFY;
  759.     ev->u      = u;
  760.     ev->s      = s;
  761.     ev->v      = v;
  762.     ev->type   = type;
  763.     ev->tv     = tv;
  764.     ev->dataSource = ds;
  765.     (*(not->notifFunction))(nev, not->pdata);
  766.        nev->eventType = oldEventType;
  767.     if (!uFixed)      ev->u = NULL;
  768.     if (!sFixed)      ev->s = NULL;
  769.     if (!vFixed)      ev->v = NULL;
  770.     }
  771. }
  772.  
  773.  
  774.  
  775. void
  776. insertNotify (RDF rdf, RDF_Notification not, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv, char* ds)
  777. {
  778.   RDF_Event nev = not->theEvent;
  779.   RDF_AssertEvent ev = &(not->theEvent->event.assert);
  780.   PRBool opTypeFixed = not->theEvent->eventType;
  781.   PRBool uFixed      = (ev->u != NULL);
  782.   PRBool sFixed        = (ev->s != NULL);
  783.   PRBool vFixed        = (ev->v != NULL);
  784.   RDF_EventType  oldEventType   = not->theEvent->eventType;
  785.   if ((!opTypeFixed ||(not->theEvent->eventType & RDF_INSERT_NOTIFY)) &&
  786.       (!uFixed      || (ev->u      == u))      &&
  787.       (!vFixed    || (ev->v      == v))       &&
  788.       (!sFixed      || (ev->s      == s))) {
  789.     /*   if     (callHasAssertions(0, rdf, u, s, v, type, !tv)) return; */
  790.     nev->eventType = RDF_INSERT_NOTIFY;
  791.     ev->u      = u;
  792.     ev->s      = s;
  793.     ev->v      = v;
  794.     ev->type   = type;
  795.     ev->tv     = tv;
  796.     ev->dataSource = ds;
  797.     (*(not->notifFunction))(nev, not->pdata);
  798.         nev->eventType = oldEventType;
  799.     if (!uFixed)      ev->u = NULL;
  800.     if (!sFixed)      ev->s = NULL;
  801.     if (!vFixed)      ev->v = NULL;
  802.     }
  803. }
  804.  
  805.  
  806.  
  807. void
  808. unassertNotify (RDF_Notification not, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, char* ds)
  809. {
  810.   RDF_Event nev = not->theEvent;
  811.   RDF_UnassertEvent ev = &(not->theEvent->event.unassert);
  812.   PRBool opTypeFixed = not->theEvent->eventType;
  813.   PRBool uFixed      = (ev->u != NULL);
  814.   PRBool sFixed        = (ev->s != NULL);
  815.   PRBool vFixed        = (ev->v != NULL);
  816.   RDF_EventType  oldEventType   = not->theEvent->eventType;
  817.   if ((!opTypeFixed ||(not->theEvent->eventType & RDF_DELETE_NOTIFY)) &&
  818.       (!uFixed      || (ev->u      == u))      &&
  819.       (!vFixed    || (ev->v      == v))       &&
  820.       (!sFixed      || (ev->s      == s))) {
  821.     nev->eventType = RDF_DELETE_NOTIFY;
  822.     ev->u      = u;
  823.     ev->s      = s;
  824.     ev->v      = v;
  825.     ev->type   = type;
  826.     ev->dataSource = ds;
  827.     (*(not->notifFunction))(nev, not->pdata);
  828.     nev->eventType = oldEventType;
  829.     if (!uFixed)      ev->u = NULL;
  830.     if (!sFixed)      ev->s = NULL;
  831.     if (!vFixed)      ev->v = NULL;
  832.     }
  833. }
  834.  
  835.  
  836.  
  837. void
  838. sendNotifications2 (RDFT r, RDF_EventType opType, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv)
  839. {
  840.   RDFL rl = r->rdf;
  841.   while (rl) {
  842.     sendNotifications(rl->rdf, opType, u, s, v, type, tv, r->url);
  843.     rl = rl->next;
  844.   }
  845. }
  846.  
  847.  
  848.  
  849. void
  850. sendNotifications (RDF rdf, RDF_EventType opType, RDF_Resource u, RDF_Resource s, void* v, RDF_ValueType type, PRBool tv, char* ds)
  851. {
  852.   RDF_Notification not;
  853.   if (rdf == NULL) return;
  854.   for (not = rdf->notifs; (not != NULL) ; not = not->next) {
  855.     if (!not->theEvent || (not->theEvent->eventType & opType)) {
  856.         RDF_EventType otype = not->theEvent->eventType;
  857.       switch (opType) 
  858.     {
  859.     case RDF_ASSERT_NOTIFY :
  860.       assertNotify(rdf, not, u, s, v, type, tv, ds);
  861.       break;
  862.     case RDF_INSERT_NOTIFY :
  863.       insertNotify(rdf, not, u, s, v, type, tv, ds);
  864.       break;
  865.     case RDF_DELETE_NOTIFY :
  866.       unassertNotify(not, u, s, v, type, ds);
  867.       break;
  868.     case RDF_KILL_NOTIFY :
  869.       break;
  870.       /*      killNotify(not, u); */
  871.     }
  872.       not->theEvent->eventType = otype;
  873.     }
  874.   }
  875. }
  876.