1 // vil_nitf2: Written by Harry Voorhees (hlv@) and Rob Radtke (rob@) of
2 // Stellar Science Ltd. Co. (stellarscience.com) for
3 // Air Force Research Laboratory, 2005.
4 
5 #ifndef VIL_NITF2_FIELD_FUNCTOR_H
6 #define VIL_NITF2_FIELD_FUNCTOR_H
7 
8 class vil_nitf2_field;
9 class vil_nitf2_enum_values;
10 class vil_nitf2_index_vector;
11 
12 #include <map>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 #include "vil_nitf2_field_sequence.h"
17 #ifdef _MSC_VER
18 #  include <vcl_msvc_warnings.h>
19 #endif
20 
21 //-----------------------------------------------------------------------------
22 //:
23 // \file
24 // \brief Functors used by NITF classes
25 //
26 // Base class for functors that define a function that takes a
27 // vil_nitf2_field_sequence and attempts to compute an "out" parameter of
28 // type T. The function also returns a bool that specifies whether the
29 // value could be computed.
30 //
31 // These functors are used to evaluate NITF field tags and invariably
32 // call vil_nitf2_field_sequence::get_value(). When calling this method,
33 // please be sure to set the argument ignore_extra_indexes to true.
34 // This will allow the functor to be used within a repeat loop
35 // and reference any preceding tag, inside or outside the repeat loop.
36 // For example, to define a field sequence like this:
37 //   FIELD A;
38 //   REPEAT i=1..N
39 //     FIELD B(i)
40 //     FIELD C(i) exists if B(i) > 0
41 //     FIELD D(i) exists if A > 0
42 // the same conditional functor can be used in the definitions of fields
43 // C and D by simply providing the name of the appropriate tag.  When
44 // the functor is evaluated, the current index (i) is used to fetch the
45 // tag. By calling get_value() with ignore_extra_indexes set to true,
46 // the value of A can be fetched without causing an error.
47 
48 template<typename T>
49 class vil_nitf2_field_functor
50 {
51  public:
52   virtual bool operator() (vil_nitf2_field_sequence* record,
53                            const vil_nitf2_index_vector& indexes, T& out_value) = 0;
54   virtual ~vil_nitf2_field_functor() = default;
55 
56   // Virtual copy method
57   virtual vil_nitf2_field_functor<T>* copy() const = 0;
58 };
59 
60 //:
61 // Functor vil_nitf2_field_value defines a function that sets its out parameter
62 // to a value of a field from a field sequence. The function returns whether
63 // the field was found. The functor is instantiated with the field's tag.
64 // The field sequence is passed to the function.
65 //
66 // You can override any value by specifying an overrideMap.  For example,
67 // if 0 was a special value that actually meant 1 but all other values
68 // (2, 3, 4...) actually meant when they were you could get that effect like this:
69 // <code>
70 // std::map< int, int > overrides;
71 // overrides.insert( std::make_pair( 0, 1 ) );
72 // new vil_nitf2_field_value( "FIELD_NAME", overrides );
73 // </code>
74 template<typename T>
75 class vil_nitf2_field_value : public vil_nitf2_field_functor<T>
76 {
77  public:
vil_nitf2_field_value(std::string tag)78   vil_nitf2_field_value(std::string tag) : tag(std::move(tag)) {}
79 
vil_nitf2_field_value(std::string tag,std::map<T,T> overrideMap)80   vil_nitf2_field_value(std::string tag, std::map<T, T> overrideMap )
81     : tag(std::move(tag)), overrides(std::move( overrideMap )) {}
82 
copy()83   vil_nitf2_field_functor<T>* copy() const override {
84     return new vil_nitf2_field_value(tag, overrides); }
85 
operator()86   bool operator() (vil_nitf2_field_sequence* record,
87                    const vil_nitf2_index_vector& indexes, T& value) override
88   {
89     bool success = record->get_value(tag, indexes, value, true);
90     if ( success ) {
91       //check to see if this value is overridden or not
92       typename std::map<T, T>::const_iterator it = overrides.find( value );
93       if ( it != overrides.end() ){
94         //found override, use it
95         value = (*it).second;
96       }
97     }
98     return success;
99   }
100 
101  private:
102   std::string tag;
103   std::map<T, T> overrides;
104 };
105 
106 //:
107 // Functor vil_nitf2_multiply_field_values defines a function that sets its out
108 // parameter to the product of the values of two fields. The predicate
109 // returns true iff both fields are found or the arg 'use_zero_if_tag_not_found';
110 // in the latter case, the out parameter is set to 0.
111 //
112 class vil_nitf2_multiply_field_values : public vil_nitf2_field_functor<int>
113 {
114  public:
115   vil_nitf2_multiply_field_values(std::string  tag_1,
116                                   std::string  tag_2,
117                                   bool use_zero_if_tag_not_found = false)
tag_1(std::move (tag_1))118     : tag_1(std::move(tag_1)),
119       tag_2(std::move(tag_2)),
120       use_zero_if_tag_not_found(use_zero_if_tag_not_found) {}
121 
copy()122   vil_nitf2_field_functor<int>* copy() const override {
123     return new vil_nitf2_multiply_field_values(
124       tag_1, tag_2, use_zero_if_tag_not_found);
125   }
126 
127   bool operator() (vil_nitf2_field_sequence* record,
128                    const vil_nitf2_index_vector& indexes, int& value) override;
129 
130  private:
131   std::string tag_1;
132   std::string tag_2;
133   bool use_zero_if_tag_not_found;
134 };
135 
136 //:
137 // Functor vil_nitf2_max_field_value_plus_offset_and_threshold defines a
138 // function that sets its out parameter to either the value of a specified
139 // field plus an offset, or a specified minimum value, whichever is greater.
140 // The function returns whether the field was found.
141 //
142 class vil_nitf2_max_field_value_plus_offset_and_threshold : public vil_nitf2_field_functor<int>
143 {
144  public:
145   vil_nitf2_max_field_value_plus_offset_and_threshold(
146     std::string tag, int offset, int min_threshold = 0, int tag_factor = 1 )
tag(std::move (tag))147     : tag(std::move(tag)), offset(offset), min_threshold(min_threshold), tag_factor( tag_factor ) {}
148 
copy()149   vil_nitf2_field_functor<int>* copy() const override {
150     return new vil_nitf2_max_field_value_plus_offset_and_threshold(
151       tag, offset, min_threshold, tag_factor); }
152 
153   bool operator() (vil_nitf2_field_sequence* record,
154                    const vil_nitf2_index_vector& indexes, int& value) override;
155 
156  private:
157   std::string tag;
158   int offset;
159   int min_threshold;
160   int tag_factor;
161 };
162 
163 //:
164 // Functor vil_nitf2_field_value_greater_than defines a comparison predicate that
165 // sets its out parameter to true if a specified field from a field
166 // sequence is found and its value is greater than a specified threshold.
167 // The predicate returns whether the field was found.
168 //
169 template<typename T>
170 class vil_nitf2_field_value_greater_than: public vil_nitf2_field_functor<bool>
171 {
172  public:
vil_nitf2_field_value_greater_than(std::string tag,T threshold)173   vil_nitf2_field_value_greater_than(std::string tag, T threshold)
174     : tag(std::move(tag)), threshold(threshold) {}
175 
copy()176   vil_nitf2_field_functor<bool>* copy() const override {
177     return new vil_nitf2_field_value_greater_than(tag, threshold); }
178 
operator()179   bool operator() (vil_nitf2_field_sequence* record,
180                    const vil_nitf2_index_vector& indexes, bool& result) override {
181     T value;
182     if (record->get_value(tag, indexes, value, true)) {
183       result = value > threshold;
184       return true;
185     }
186     else {
187       return false;
188     }
189   }
190  private:
191   std::string tag;
192   T threshold;
193 };
194 
195 //:
196 // Functor vil_nitf2_field_specified defines a comparison predicate that sets
197 // its out parameter to true iff the specified field is not blank.
198 //
199 class vil_nitf2_field_specified: public vil_nitf2_field_functor<bool>
200 {
201  public:
vil_nitf2_field_specified(std::string tag)202   vil_nitf2_field_specified(std::string tag) : tag(std::move(tag)) {}
203 
copy()204   vil_nitf2_field_functor<bool>* copy() const override {
205     return new vil_nitf2_field_specified(tag); }
206 
207   bool operator() (vil_nitf2_field_sequence* record,
208                    const vil_nitf2_index_vector& indexes, bool& result) override;
209 
210  private:
211   std::string tag;
212 };
213 
214 //:
215 // Functor vil_nitf2_field_value_one_of defines a predicate that sets its out
216 // parameter to true iff the value of the specified tag equals one of
217 // the elements of a std::vector of acceptable values.
218 //
219 template<typename T>
220 class vil_nitf2_field_value_one_of: public vil_nitf2_field_functor<bool>
221 {
222  public:
223   /// Constructor to specify a std::vector of acceptable values
vil_nitf2_field_value_one_of(std::string tag,std::vector<T> acceptable_values)224   vil_nitf2_field_value_one_of(std::string tag, std::vector<T> acceptable_values)
225     : tag(std::move(tag)), acceptable_values(std::move(acceptable_values)) {}
226 
227   /// Constructor to specify only one acceptable value
vil_nitf2_field_value_one_of(std::string tag,T acceptable_value)228   vil_nitf2_field_value_one_of(std::string tag, T acceptable_value)
229     : tag(std::move(tag)), acceptable_values(1, acceptable_value) {}
230 
copy()231   vil_nitf2_field_functor<bool>* copy() const override {
232     return new vil_nitf2_field_value_one_of(tag, acceptable_values); }
233 
operator()234   bool operator() (vil_nitf2_field_sequence* record,
235                    const vil_nitf2_index_vector& indexes, bool& result) override
236   {
237     result = false;
238     T val;
239     if (record->get_value(tag, indexes, val, true)) {
240       typename std::vector<T>::iterator it;
241       for (it = acceptable_values.begin(); it != acceptable_values.end(); ++it) {
242         if ((*it) == val) {
243           result = true;
244           break;
245         }
246       }
247       return true;
248     }
249     // Field not defined
250     return false;
251   }
252 
253  protected:
254   std::string tag;
255   std::vector<T> acceptable_values;
256 };
257 
258 //:
259 // Functor vil_nitf2_choose_field_value defines a function that sets its out
260 // parameter to a value of one of two fields of a field sequence. The
261 // field chosen is determined by the evaluating the functor passed as
262 // argument 'choose_tag_1_predicate': tag_1 is chosen if it evaluates to true;
263 // tag_2, otherwise.
264 //
265 template<typename T>
266 class vil_nitf2_choose_field_value : public vil_nitf2_field_functor<T>
267 {
268  public:
269   /// Constructor. I take ownership of inDecider.
vil_nitf2_choose_field_value(std::string tag_1,std::string tag_2,vil_nitf2_field_functor<bool> * choose_tag_1_predicate)270   vil_nitf2_choose_field_value(std::string  tag_1, std::string  tag_2,
271                                vil_nitf2_field_functor<bool>* choose_tag_1_predicate)
272     : tag_1(std::move(tag_1)), tag_2(std::move(tag_2)), choose_tag_1_predicate(choose_tag_1_predicate) {}
273 
copy()274   vil_nitf2_field_functor<T>* copy() const override {
275     return new vil_nitf2_choose_field_value(
276       tag_1, tag_2, choose_tag_1_predicate->copy()); }
277 
~vil_nitf2_choose_field_value()278   ~vil_nitf2_choose_field_value() override {
279     if (choose_tag_1_predicate) delete choose_tag_1_predicate;
280   }
281 
operator()282   bool operator() (vil_nitf2_field_sequence* record,
283                    const vil_nitf2_index_vector& indexes, T& value) override {
284     bool choose_tag_1;
285     if ((*choose_tag_1_predicate)(record, indexes, choose_tag_1)) {
286       if (choose_tag_1) return record->get_value(tag_1, indexes, value, true);
287       else return record->get_value(tag_2, indexes, value, true);
288     }
289     else return false;
290   }
291  private:
292   std::string tag_1;
293   std::string tag_2;
294   vil_nitf2_field_functor<bool>* choose_tag_1_predicate;
295 };
296 
297 // Functor vil_nitf2_constant_functor defines a function that sets its
298 // output value to a constant that does not depend on the field sequence
299 // passed to it.
300 //
301 template<typename T>
302 class vil_nitf2_constant_functor : public vil_nitf2_field_functor<T>
303 {
304  public:
vil_nitf2_constant_functor(T value)305   vil_nitf2_constant_functor(T value) : value_(value) {}
306 
copy()307   vil_nitf2_constant_functor* copy() const override {
308     return new vil_nitf2_constant_functor(value_);
309   }
310 
311   ~vil_nitf2_constant_functor() override = default;
312 
operator()313   bool operator() (vil_nitf2_field_sequence* /*record*/,
314                   const vil_nitf2_index_vector& /*indexes*/, T& value) override {
315     value = value_;
316     return true;
317   }
318 
319  private:
320   T value_;
321 };
322 
323 #endif // VIL_NITF2_FIELD_FUNCTOR_H
324