aboutsummaryrefslogtreecommitdiffstats
path: root/libical/src/libicalss/icalgauge.c
blob: 60ce1587cd40a16ad34c3c47a3781a29d4c760e8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
/* -*- Mode: C -*- */
/*======================================================================
 FILE: icalgauge.c
 CREATOR: eric 23 December 1999


 $Id$
 $Locker$

 (C) COPYRIGHT 2000, Eric Busboom, http://www.softwarestudio.org

 This program is free software; you can redistribute it and/or modify
 it under the terms of either: 

    The LGPL as published by the Free Software Foundation, version
    2.1, available at: http://www.fsf.org/copyleft/lesser.html

  Or:

    The Mozilla Public License Version 1.0. You may obtain a copy of
    the License at http://www.mozilla.org/MPL/

 The Original Code is eric. The Initial Developer of the Original
 Code is Eric Busboom


======================================================================*/

#include "ical.h"

/* Convert a VQUERY component into a gauge */
icalcomponent* icalgauge_make_gauge(icalcomponent* query);

/* icaldirset_test compares a component against a gauge, and returns
   true if the component passes the test 

   The gauge is a VCALENDAR component that specifies how to test the
   target components. The guage holds a collection of VEVENT, VTODO or
   VJOURNAL sub-components. Each of the sub-components has a
   collection of properties that are compared to corresponding
   properties in the target component, according to the
   X-LIC-COMPARETYPE parameters to the gauge's properties.

   When a gauge has several sub-components, the results of testing the
   target against each of them is ORed together - the target
   component will pass if it matches any of the sub-components in the
   gauge. However, the results of matching the proeprties in a
   sub-component are ANDed -- the target must match every property in
   a gauge sub-component to match the sub-component.

   Here is an example:

   BEGIN:XROOT
   BEGIN:VCOMPONENT
   BEGIN:VEVENT
   DTSTART;X-LIC-COMPARETYPE=LESS:19981025T020000
   ORGANIZER;X-LIC-COMPARETYPE=EQUAL:mrbig@host.com 
   END:VEVENT
   BEGIN:VEVENT
   LOCATION;X-LIC-COMPARETYPE=EQUAL:McNary's Pub
   END:VEVENT
   END:VCALENDAR
   END:XROOT

   This gauge has two sub-components; one which will match a VEVENT
   based on start time, and organizer, and another that matches based
   on LOCATION. A target component will pass the test if it matched
   either of the sub-components.
   
  */


int icalgauge_test_recurse(icalcomponent* comp, icalcomponent* gauge)
{
    int pass = 1,localpass = 0;
    icalproperty *p;
    icalcomponent *child,*subgauge; 
    icalcomponent_kind gaugekind, compkind;

    icalerror_check_arg_rz( (comp!=0), "comp");
    icalerror_check_arg_rz( (gauge!=0), "gauge");

    gaugekind = icalcomponent_isa(gauge);
    compkind = icalcomponent_isa(comp);

    if( ! (gaugekind == compkind || gaugekind == ICAL_ANY_COMPONENT) ){
    return 0;
    }   

    /* Test properties. For each property in the gauge, search through
       the component for a similar property. If one is found, compare
       the two properties value with the comparison specified in the
       gauge with the X-LIC-COMPARETYPE parameter */
    
    for(p = icalcomponent_get_first_property(gauge,ICAL_ANY_PROPERTY);
    p != 0;
    p = icalcomponent_get_next_property(gauge,ICAL_ANY_PROPERTY)){
    
    icalproperty* targetprop; 
    icalparameter* compareparam;
    icalparameter_xliccomparetype compare;
    int rel; /* The relationship between the gauge and target values.*/
    
    /* Extract the comparison type from the gauge. If there is no
       comparison type, assume that it is "EQUAL" */
    
    compareparam = icalproperty_get_first_parameter(
        p,
        ICAL_XLICCOMPARETYPE_PARAMETER);
    
    if (compareparam!=0){
        compare = icalparameter_get_xliccomparetype(compareparam);
    } else {
        compare = ICAL_XLICCOMPARETYPE_EQUAL;
    }
    
    /* Find a property in the component that has the same type
       as the gauge property. HACK -- multiples of a single
       property type in the gauge will match only the first
       instance in the component */
    
    targetprop = icalcomponent_get_first_property(comp,
                              icalproperty_isa(p));
    
    if(targetprop != 0){
    
        /* Compare the values of the gauge property and the target
           property */
        
        rel = icalvalue_compare(icalproperty_get_value(p),
                    icalproperty_get_value(targetprop));
        
        /* Now see if the comparison is equavalent to the comparison
           specified in the gauge */
        
        if (rel == compare){ 
        localpass++; 
        } else if (compare == ICAL_XLICCOMPARETYPE_LESSEQUAL && 
               ( rel == ICAL_XLICCOMPARETYPE_LESS ||
             rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
        localpass++;
        } else if (compare == ICAL_XLICCOMPARETYPE_GREATEREQUAL && 
               ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
             rel == ICAL_XLICCOMPARETYPE_EQUAL)) {
        localpass++;
        } else if (compare == ICAL_XLICCOMPARETYPE_NOTEQUAL && 
               ( rel == ICAL_XLICCOMPARETYPE_GREATER ||
             rel == ICAL_XLICCOMPARETYPE_LESS)) {
        localpass++;
        } else {
        localpass = 0;
        }
        
        pass = pass && (localpass>0);
    }
    }
    
    /* Test subcomponents. Look for a child component that has a
       counterpart in the gauge. If one is found, recursively call
       icaldirset_test */
    
    for(subgauge = icalcomponent_get_first_component(gauge,ICAL_ANY_COMPONENT);
    subgauge != 0;
    subgauge = icalcomponent_get_next_component(gauge,ICAL_ANY_COMPONENT)){
    
    gaugekind = icalcomponent_isa(subgauge);

    if (gaugekind == ICAL_ANY_COMPONENT){
        child = icalcomponent_get_first_component(comp,ICAL_ANY_COMPONENT);
    } else {
        child = icalcomponent_get_first_component(comp,gaugekind);
    }
    
    if(child !=0){
        localpass = icalgauge_test_recurse(child,subgauge);
        pass = pass && localpass;
    } else {
        pass = 0;
    }
    }
    
    return pass;   
}

/* guagecontainer is an XROOT component that holds several gauges. The
   results of comparing against these gauges are ORed together in this
   routine */
int icalgauge_test(icalcomponent* comp, 
           icalcomponent* gaugecontainer)
{
    int pass = 0;
    icalcomponent *gauge; 

    icalerror_check_arg_rz( (comp!=0), "comp");
    icalerror_check_arg_rz( (gauge!=0), "gauge");
    
    for(gauge = icalcomponent_get_first_component(gaugecontainer,ICAL_ANY_COMPONENT);
    gauge != 0;
    gauge = icalcomponent_get_next_component(gaugecontainer,ICAL_ANY_COMPONENT)){

    pass += icalgauge_test_recurse(comp, gauge);
    }

    return pass>0;

}