Back to index

lightning-sunbird  0.9+nobinonly
icalgauge.c
Go to the documentation of this file.
00001 /* -*- Mode: C -*- */
00002 /*======================================================================
00003  FILE: icalgauge.c
00004  CREATOR: eric 23 December 1999
00005 
00006 
00007  $Id: icalgauge.c,v 1.13 2002/09/26 22:26:06 lindner Exp $
00008  $Locker:  $
00009 
00010  (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org
00011 
00012  This program is free software; you can redistribute it and/or modify
00013  it under the terms of either: 
00014 
00015     The LGPL as published by the Free Software Foundation, version
00016     2.1, available at: http://www.fsf.org/copyleft/lesser.html
00017 
00018   Or:
00019 
00020     The Mozilla Public License Version 1.0. You may obtain a copy of
00021     the License at http://www.mozilla.org/MPL/
00022 
00023  The Original Code is eric. The Initial Developer of the Original
00024  Code is Eric Busboom
00025 
00026 
00027 ======================================================================*/
00028 
00029 #include "ical.h"
00030 #include "icalgauge.h"
00031 #include "icalgaugeimpl.h"
00032 #include <stdlib.h>
00033 
00034 #include "icalssyacc.h"
00035 
00036 typedef void* yyscan_t;
00037 
00038 int ssparse(yyscan_t );
00039 
00040 
00041 icalgauge* icalgauge_new_from_sql(char* sql, int expand)
00042 {
00043     struct icalgauge_impl *impl;
00044     yyscan_t yy_globals = NULL;
00045 
00046     int r;
00047     
00048     if ( ( impl = (struct icalgauge_impl*)
00049           malloc(sizeof(struct icalgauge_impl))) == 0) {
00050        icalerror_set_errno(ICAL_NEWFAILED_ERROR);
00051        return 0;
00052     }
00053 
00054     impl->select = pvl_newlist();
00055     impl->from = pvl_newlist();
00056     impl->where = pvl_newlist();
00057     impl->expand = expand;
00058 
00059     sslex_init(&yy_globals);
00060 
00061     ssset_extra(impl, yy_globals);
00062 
00063     ss_scan_string(sql, yy_globals);
00064 
00065     r = ssparse(yy_globals);
00066     sslex_destroy(yy_globals);
00067 
00068        if (r == 0) {
00069            return impl;
00070        }
00071        else {
00072                icalgauge_free(impl);
00073                return NULL;
00074        }
00075 }
00076 
00077 int icalgauge_get_expand(icalgauge* gauge)
00078 {
00079 return (gauge->expand);
00080 
00081 }
00082 
00083 void icalgauge_free(icalgauge* gauge)
00084 {
00085       struct icalgauge_where *w;
00086 
00087       assert(gauge->select != 0);
00088       assert(gauge->where != 0);
00089       assert(gauge->from != 0);
00090 
00091       if(gauge->select){
00092          while( (w=pvl_pop(gauge->select)) != 0){
00093              if(w->value != 0){
00094                 free(w->value);
00095              }
00096              free(w);
00097          }
00098          pvl_free(gauge->select);
00099          gauge->select = 0;
00100       }
00101 
00102       if(gauge->where){
00103          while( (w=pvl_pop(gauge->where)) != 0){
00104              
00105              if(w->value != 0){
00106                 free(w->value);
00107              }
00108              free(w);
00109          }
00110          pvl_free(gauge->where);
00111          gauge->where = 0;
00112       }
00113 
00114       if(gauge->from){
00115          pvl_free(gauge->from);
00116          gauge->from = 0;
00117       }
00118 
00119          free(gauge);
00120       
00121 }
00122 
00123 
00125 icalcomponent* icalgauge_make_gauge(icalcomponent* query);
00126 
00163 int icalgauge_compare_recurse(icalcomponent* comp, icalcomponent* gauge)
00164 {
00165     int pass = 1,localpass = 0;
00166     icalproperty *p;
00167     icalcomponent *child,*subgauge; 
00168     icalcomponent_kind gaugekind, compkind;
00169 
00170     icalerror_check_arg_rz( (comp!=0), "comp");
00171     icalerror_check_arg_rz( (gauge!=0), "gauge");
00172 
00173     gaugekind = icalcomponent_isa(gauge);
00174     compkind = icalcomponent_isa(comp);
00175 
00176     if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){
00177        return 0;
00178     }   
00179 
00180     /* Test properties. For each property in the gauge, search through
00181        the component for a similar property. If one is found, compare
00182        the two properties value with the comparison specified in the
00183        gauge with the X-LIC-COMPARETYPE parameter */
00184     
00185     for(p = icalcomponent_get_first_property(gauge,ICAL_ANY_PROPERTY);
00186        p != 0;
00187        p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){
00188        
00189        icalproperty* targetprop; 
00190        icalparameter* compareparam;
00191        icalparameter_xliccomparetype compare;
00192        int rel; /* The relationship between the gauge and target values.*/
00193        
00194        /* Extract the comparison type from the gauge. If there is no
00195           comparison type, assume that it is "EQUAL" */
00196        
00197        compareparam = icalproperty_get_first_parameter(
00198            p,
00199            ICAL_XLICCOMPARETYPE_PARAMETER);
00200        
00201        if (compareparam!=0){
00202            compare = icalparameter_get_xliccomparetype(compareparam);
00203        } else {
00204            compare = ICAL_XLICCOMPARETYPE_EQUAL;
00205        }
00206        
00207        /* Find a property in the component that has the same type
00208           as the gauge property. HACK -- multiples of a single
00209           property type in the gauge will match only the first
00210           instance in the component */
00211        
00212        targetprop = icalcomponent_get_first_property(comp,
00213                                                 icalproperty_isa(p));
00214        
00215        if(targetprop != 0){
00216        
00217            /* Compare the values of the gauge property and the target
00218               property */
00219            
00220            rel = icalvalue_compare(icalproperty_get_value(p),
00221                                 icalproperty_get_value(targetprop));
00222            
00223            /* Now see if the comparison is equavalent to the comparison
00224               specified in the gauge */
00225            
00226            if (rel == compare){ 
00227               localpass++; 
00228            } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL && 
00229                      ( rel == ICAL_XLICCOMPARETYPE_LESS ||
00230                       rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
00231               localpass++;
00232            } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL && 
00233                      ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
00234                       rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
00235               localpass++;
00236            } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL && 
00237                      ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
00238                       rel == ICAL_XLICCOMPARETYPE_LESS)) {
00239               localpass++;
00240            } else {
00241               localpass = 0;
00242            }
00243            
00244            pass = pass && (localpass>0);
00245        }
00246     }
00247     
00248     /* Test subcomponents. Look for a child component that has a
00249        counterpart in the gauge. If one is found, recursively call
00250        icaldirset_test */
00251     
00252     for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT);
00253        subgauge != 0;
00254        subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){
00255        
00256        gaugekind = icalcomponent_isa(subgauge);
00257 
00258        if (gaugekind == ICAL_ANY_COMPONENT){
00259            child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
00260        } else {
00261            child = icalcomponent_get_first_component(comp,gaugekind);
00262        }
00263        
00264        if(child !=0){
00265            localpass = icalgauge_compare_recurse(child,subgauge);
00266            pass = pass && localpass;
00267        } else {
00268            pass = 0;
00269        }
00270     }
00271     
00272     return pass;   
00273 }
00274 
00275 
00276 int icalgauge_compare(icalgauge* gauge,icalcomponent* comp)
00277 {
00278 
00279     icalcomponent *inner; 
00280     int local_pass = 0;
00281     int last_clause = 1, this_clause = 1;
00282     pvl_elem e;
00283     icalcomponent_kind kind;
00284     icalproperty *rrule;
00285     int compare_recur = 0;
00286 
00287 
00288     icalerror_check_arg_rz( (comp!=0), "comp");
00289     icalerror_check_arg_rz( (gauge!=0), "gauge");
00290     
00291     if (gauge == 0 || comp == 0) return 0;
00292  
00293     inner = icalcomponent_get_first_real_component(comp);
00294 
00295     if(inner == 0){
00296        /* Wally Yau: our component is not always wrapped with
00297         * a <VCALENDAR>. It's not an error. 
00298         * icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
00299         * return 0; */
00300        kind = icalcomponent_isa(comp);
00301        if(kind == ICAL_VEVENT_COMPONENT ||
00302            kind == ICAL_VTODO_COMPONENT ||
00303            kind == ICAL_VJOURNAL_COMPONENT ||
00304            kind == ICAL_VQUERY_COMPONENT ||
00305            kind == ICAL_VAGENDA_COMPONENT){
00306               inner = comp;
00307            }
00308        else {
00309            icalerror_set_errno(ICAL_MALFORMEDDATA_ERROR);
00310            return 0;
00311        }
00312         inner = comp;
00313     }
00314 
00315     /* Check that this component is one of the FROM types */
00316     local_pass = 0;
00317     for(e = pvl_head(gauge->from);e!=0;e=pvl_next(e)){
00318        icalcomponent_kind k = (icalcomponent_kind)pvl_data(e);
00319 
00320        if(k == icalcomponent_isa(inner)){
00321            local_pass=1;
00322        }
00323     }
00324     
00325     if(local_pass == 0){
00326        return 0;
00327     }
00328 
00329     
00330     /**** Check each where clause against the component ****/
00331     for(e = pvl_head(gauge->where);e!=0;e=pvl_next(e)){
00332        struct icalgauge_where *w = pvl_data(e);
00333        icalcomponent *sub_comp;
00334        icalvalue *v;
00335        icalproperty *prop;
00336        icalvalue_kind vk;
00337 
00338        if(w->prop == ICAL_NO_PROPERTY || w->value == 0){
00339            icalerror_set_errno(ICAL_INTERNAL_ERROR);
00340            return 0;
00341        }
00342 
00343        /* First, create a value from the gauge */
00344        vk = icalenum_property_kind_to_value_kind(w->prop);
00345 
00346        if(vk == ICAL_NO_VALUE){
00347             icalerror_set_errno(ICAL_INTERNAL_ERROR);
00348            return 0;
00349        }
00350 
00351         if (w->compare == ICALGAUGECOMPARE_ISNULL || w->compare == ICALGAUGECOMPARE_ISNOTNULL)
00352            v = icalvalue_new(vk);
00353         else
00354          v = icalvalue_new_from_string(vk,w->value);
00355 
00356        if (v == 0){
00357            /* Keep error set by icalvalue_from-string*/
00358            return 0;
00359        }
00360            
00361        /* Now find the corresponding property in the component,
00362           descending into a sub-component if necessary */
00363 
00364        if(w->comp == ICAL_NO_COMPONENT){
00365            sub_comp = inner;
00366        } else {
00367            sub_comp = icalcomponent_get_first_component(inner,w->comp);
00368            if(sub_comp == 0){
00369               return 0;
00370            }
00371        }         
00372 
00373         /* check if it is a recurring */
00374         rrule = icalcomponent_get_first_property(sub_comp,ICAL_RRULE_PROPERTY);
00375 
00376         if (gauge->expand
00377             && rrule) {
00378 
00379             if (w->prop == ICAL_DTSTART_PROPERTY || 
00380                 w->prop == ICAL_DTEND_PROPERTY || 
00381                 w->prop == ICAL_DUE_PROPERTY){
00383                 compare_recur = 1;
00384             } 
00385 
00386        }
00387 
00388 
00389        this_clause = 0;
00390        local_pass = (w->compare == ICALGAUGECOMPARE_ISNULL) ? 1 : 0;
00391 
00392        for(prop = icalcomponent_get_first_property(sub_comp,w->prop);
00393            prop != 0;
00394            prop = icalcomponent_get_next_property(sub_comp,w->prop)){
00395            icalvalue* prop_value;
00396            icalgaugecompare relation;
00397 
00398             if (w->compare == ICALGAUGECOMPARE_ISNULL) {
00399                 local_pass = 0;
00400                 break;
00401             }
00402 
00403             if (w->compare == ICALGAUGECOMPARE_ISNOTNULL) {
00404                 local_pass = 1;
00405                 break;
00406             }
00407 
00408             if (compare_recur) {
00409                 icalproperty *p = icalcomponent_get_first_property(sub_comp, ICAL_RECURRENCEID_PROPERTY);   
00410                 prop_value = icalproperty_get_value(p);
00411             }
00412             else /* prop value from this component */
00413            prop_value = icalproperty_get_value(prop);
00414 
00415            relation = (icalgaugecompare)icalvalue_compare(prop_value,v);
00416            
00417            if (relation  == w->compare){ 
00418               local_pass++; 
00419            } else if (w->compare == ICALGAUGECOMPARE_LESSEQUAL && 
00420                      ( relation  == ICALGAUGECOMPARE_LESS ||
00421                       relation  == ICALGAUGECOMPARE_EQUAL)) {
00422               local_pass++;
00423            } else if (w->compare == ICALGAUGECOMPARE_GREATEREQUAL && 
00424                      ( relation  == ICALGAUGECOMPARE_GREATER ||
00425                       relation  == ICALGAUGECOMPARE_EQUAL)) {
00426               local_pass++;
00427            } else if (w->compare == ICALGAUGECOMPARE_NOTEQUAL && 
00428                      ( relation  == ICALGAUGECOMPARE_GREATER ||
00429                       relation  == ICALGAUGECOMPARE_LESS)) {
00430               local_pass++;
00431            } else {
00432               local_pass = 0;
00433            }
00434        }
00435     
00436     
00437        this_clause = local_pass > 0 ? 1 : 0;
00438 
00439 
00440        /* Now look at the logic operator for this clause to see how
00441            the value should be merge with the previous clause */
00442 
00443        if(w->logic == ICALGAUGELOGIC_AND){
00444            last_clause = this_clause && last_clause;
00445        } else if(w->logic == ICALGAUGELOGIC_OR) {
00446            last_clause = this_clause || last_clause;
00447        } else {
00448            last_clause = this_clause;
00449        }
00450 
00451        icalvalue_free(v);
00452 
00453     }/**** check next one in where clause ****/
00454 
00455     return last_clause;
00456 
00457 }
00458     
00463 void icalgauge_dump(icalgauge* gauge)
00464 {
00465 
00466     pvl_elem p;
00467   
00468     printf("--- Select ---\n");
00469     for(p = pvl_head(gauge->select);p!=0;p=pvl_next(p)){
00470        struct icalgauge_where *w = pvl_data(p);
00471 
00472        if(w->comp != ICAL_NO_COMPONENT){
00473            printf("%s ",icalenum_component_kind_to_string(w->comp));
00474        }
00475 
00476        if(w->prop != ICAL_NO_PROPERTY){
00477            printf("%s ",icalenum_property_kind_to_string(w->prop));
00478        }
00479        
00480        if (w->compare != ICALGAUGECOMPARE_NONE){
00481            printf("%d ",w->compare);
00482        }
00483 
00484 
00485        if (w->value!=0){
00486            printf("%s",w->value);
00487        }
00488 
00489 
00490        printf("\n");
00491     }
00492 
00493     printf("--- From ---\n");
00494     for(p = pvl_head(gauge->from);p!=0;p=pvl_next(p)){
00495        icalcomponent_kind k = (icalcomponent_kind)pvl_data(p);
00496 
00497        printf("%s\n",icalenum_component_kind_to_string(k));
00498     }
00499 
00500     printf("--- Where ---\n");
00501     for(p = pvl_head(gauge->where);p!=0;p=pvl_next(p)){
00502        struct icalgauge_where *w = pvl_data(p);
00503 
00504        if(w->logic != ICALGAUGELOGIC_NONE){
00505            printf("%d ",w->logic);
00506        }
00507        
00508        if(w->comp != ICAL_NO_COMPONENT){
00509            printf("%s ",icalenum_component_kind_to_string(w->comp));
00510        }
00511 
00512        if(w->prop != ICAL_NO_PROPERTY){
00513            printf("%s ",icalenum_property_kind_to_string(w->prop));
00514        }
00515        
00516        if (w->compare != ICALGAUGECOMPARE_NONE){
00517            printf("%d ",w->compare);
00518        }
00519 
00520 
00521        if (w->value!=0){
00522            printf("%s",w->value);
00523        }
00524 
00525 
00526        printf("\n");
00527     }
00528 }
00529