Line data Source code
1 : /* File: data_database_classifier_reader.c; Copyright and License: see below */
2 :
3 : #include "storage/data_database_classifier_reader.h"
4 : #include "storage/data_database_borrowed_stmt.h"
5 : #include "u8/u8_trace.h"
6 : #include "u8/u8_log.h"
7 : #include "utf8stringbuf/utf8stringbuf.h"
8 : #include <sqlite3.h>
9 : #include <assert.h>
10 :
11 112 : u8_error_t data_database_classifier_reader_init ( data_database_classifier_reader_t *this_, data_database_t *database )
12 : {
13 112 : U8_TRACE_BEGIN();
14 112 : assert( NULL != database );
15 112 : u8_error_t result = U8_ERROR_NONE;
16 :
17 112 : (*this_).database = database;
18 :
19 112 : (*this_).statement_classifier_by_id = NULL;
20 112 : (*this_).statement_classifier_by_name = NULL;
21 112 : (*this_).statement_classifier_by_uuid = NULL;
22 112 : (*this_).statement_classifiers_all = NULL;
23 112 : (*this_).statement_classifiers_all_hierarchical = NULL;
24 :
25 112 : (*this_).statement_feature_by_id = NULL;
26 112 : (*this_).statement_feature_by_uuid = NULL;
27 112 : (*this_).statement_features_by_classifier_id = NULL;
28 112 : (*this_).statement_features_by_diagram_id = NULL;
29 :
30 112 : (*this_).statement_relationship_by_id = NULL;
31 112 : (*this_).statement_relationship_by_uuid = NULL;
32 112 : (*this_).statement_relationships_by_classifier_id = NULL;
33 112 : (*this_).statement_relationships_by_feature_id = NULL;
34 112 : (*this_).statement_relationships_by_diagram_id = NULL;
35 :
36 112 : result |= data_database_classifier_reader_private_open( this_ );
37 :
38 112 : U8_TRACE_END_ERR(result);
39 112 : return result;
40 : }
41 :
42 112 : u8_error_t data_database_classifier_reader_destroy ( data_database_classifier_reader_t *this_ )
43 : {
44 112 : U8_TRACE_BEGIN();
45 112 : u8_error_t result = U8_ERROR_NONE;
46 :
47 112 : result |= data_database_classifier_reader_private_close( this_ );
48 :
49 112 : (*this_).database = NULL;
50 :
51 112 : U8_TRACE_END_ERR(result);
52 112 : return result;
53 : }
54 :
55 : /* ================================ CLASSIFIER ================================ */
56 :
57 : /*!
58 : * \brief predefined search statement to find a classifier by id
59 : */
60 : static const char DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_ID[] =
61 : "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid "
62 : "FROM classifiers WHERE id=?;";
63 :
64 : /*!
65 : * \brief predefined search statement to find a classifier by uuid
66 : */
67 : static const char DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_UUID[] =
68 : "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid "
69 : "FROM classifiers WHERE uuid=?;";
70 :
71 : /*!
72 : * \brief predefined search statement to find a classifier by name
73 : */
74 : static const char DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_NAME[] =
75 : "SELECT id,main_type,stereotype,name,description,x_order,y_order,list_order,uuid "
76 : "FROM classifiers WHERE name=?;";
77 :
78 : /*!
79 : * \brief the column id of the result where this parameter is stored: id
80 : */
81 : static const int RESULT_CLASSIFIER_ID_COLUMN = 0;
82 :
83 : /*!
84 : * \brief the column id of the result where this parameter is stored: main_type
85 : */
86 : static const int RESULT_CLASSIFIER_MAIN_TYPE_COLUMN = 1;
87 :
88 : /*!
89 : * \brief the column id of the result where this parameter is stored: stereotype
90 : */
91 : static const int RESULT_CLASSIFIER_STEREOTYPE_COLUMN = 2;
92 :
93 : /*!
94 : * \brief the column id of the result where this parameter is stored: name
95 : */
96 : static const int RESULT_CLASSIFIER_NAME_COLUMN = 3;
97 :
98 : /*!
99 : * \brief the column id of the result where this parameter is stored: description
100 : */
101 : static const int RESULT_CLASSIFIER_DESCRIPTION_COLUMN = 4;
102 :
103 : /*!
104 : * \brief the column id of the result where this parameter is stored: x_order
105 : */
106 : static const int RESULT_CLASSIFIER_X_ORDER_COLUMN = 5;
107 :
108 : /*!
109 : * \brief the column id of the result where this parameter is stored: y_order
110 : */
111 : static const int RESULT_CLASSIFIER_Y_ORDER_COLUMN = 6;
112 :
113 : /*!
114 : * \brief the column id of the result where this parameter is stored: list_order
115 : */
116 : static const int RESULT_CLASSIFIER_LIST_ORDER_COLUMN = 7;
117 :
118 : /*!
119 : * \brief the column id of the result where this parameter is stored: uuid
120 : */
121 : static const int RESULT_CLASSIFIER_UUID_COLUMN = 8;
122 :
123 13 : u8_error_t data_database_classifier_reader_get_classifier_by_id( data_database_classifier_reader_t *this_,
124 : data_row_t id,
125 : data_classifier_t *out_classifier )
126 : {
127 13 : U8_TRACE_BEGIN();
128 13 : assert( NULL != out_classifier );
129 13 : u8_error_t result = U8_ERROR_NONE;
130 : int sqlite_err;
131 : sqlite3_stmt *prepared_statement;
132 :
133 : {
134 13 : prepared_statement = (*this_).statement_classifier_by_id;
135 :
136 13 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, id );
137 :
138 13 : U8_TRACE_INFO( "sqlite3_step()" );
139 13 : sqlite_err = sqlite3_step( prepared_statement );
140 13 : if ( SQLITE_ROW != sqlite_err )
141 : {
142 : /* this situation may happen if a classifier is deleted that is shown in the attributes editor */
143 0 : U8_TRACE_INFO_INT( "sqlite3_step did not find a row for id", id );
144 0 : result |= U8_ERROR_DB_STRUCTURE; /* non-existing ids are worse than U8_ERROR_NOT_FOUND */
145 : }
146 :
147 13 : if ( SQLITE_ROW == sqlite_err )
148 : {
149 13 : result |= data_classifier_init( out_classifier,
150 13 : sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIER_ID_COLUMN ),
151 13 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
152 13 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_STEREOTYPE_COLUMN ),
153 13 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
154 13 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_DESCRIPTION_COLUMN ),
155 13 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_X_ORDER_COLUMN ),
156 13 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_Y_ORDER_COLUMN ),
157 13 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_LIST_ORDER_COLUMN ),
158 13 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_UUID_COLUMN )
159 : );
160 :
161 13 : data_classifier_trace( out_classifier );
162 :
163 13 : sqlite_err = sqlite3_step( prepared_statement );
164 13 : if ( SQLITE_DONE != sqlite_err )
165 : {
166 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
167 0 : result |= U8_ERROR_DB_STRUCTURE;
168 : }
169 : }
170 : }
171 :
172 13 : U8_TRACE_END_ERR( result );
173 13 : return result;
174 : }
175 :
176 57 : u8_error_t data_database_classifier_reader_get_classifier_by_name( data_database_classifier_reader_t *this_,
177 : const char *name,
178 : data_classifier_t *out_classifier )
179 : {
180 57 : U8_TRACE_BEGIN();
181 57 : assert( NULL != out_classifier );
182 57 : assert( NULL != name );
183 57 : u8_error_t result = U8_ERROR_NONE;
184 : int sqlite_err;
185 : sqlite3_stmt *prepared_statement;
186 :
187 : {
188 57 : prepared_statement = (*this_).statement_classifier_by_name;
189 :
190 57 : result |= data_database_classifier_reader_private_bind_text_to_statement( this_, prepared_statement, name );
191 :
192 57 : U8_TRACE_INFO( "sqlite3_step()" );
193 57 : sqlite_err = sqlite3_step( prepared_statement );
194 57 : if ( SQLITE_ROW != sqlite_err )
195 : {
196 6 : U8_TRACE_INFO_STR( "sqlite3_step did not find a row for name", name );
197 6 : result |= U8_ERROR_NOT_FOUND;
198 : }
199 :
200 57 : if ( SQLITE_ROW == sqlite_err )
201 : {
202 51 : result |= data_classifier_init( out_classifier,
203 51 : sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIER_ID_COLUMN ),
204 51 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
205 51 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_STEREOTYPE_COLUMN ),
206 51 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
207 51 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_DESCRIPTION_COLUMN ),
208 51 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_X_ORDER_COLUMN ),
209 51 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_Y_ORDER_COLUMN ),
210 51 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_LIST_ORDER_COLUMN ),
211 51 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_UUID_COLUMN )
212 : );
213 :
214 51 : data_classifier_trace( out_classifier );
215 :
216 51 : sqlite_err = sqlite3_step( prepared_statement );
217 51 : if ( SQLITE_DONE != sqlite_err )
218 : {
219 0 : U8_LOG_ERROR_INT( "sqlite3_step not done yet:", sqlite_err );
220 0 : result |= U8_ERROR_DB_STRUCTURE;
221 : }
222 : }
223 : }
224 :
225 57 : U8_TRACE_END_ERR( result );
226 57 : return result;
227 : }
228 :
229 69 : u8_error_t data_database_classifier_reader_get_classifier_by_uuid ( data_database_classifier_reader_t *this_,
230 : const char *uuid,
231 : data_classifier_t *out_classifier )
232 : {
233 69 : U8_TRACE_BEGIN();
234 69 : assert( NULL != out_classifier );
235 69 : assert( NULL != uuid );
236 69 : u8_error_t result = U8_ERROR_NONE;
237 : int sqlite_err;
238 : sqlite3_stmt *prepared_statement;
239 :
240 : {
241 69 : prepared_statement = (*this_).statement_classifier_by_uuid;
242 :
243 69 : result |= data_database_classifier_reader_private_bind_text_to_statement( this_, prepared_statement, uuid );
244 :
245 69 : U8_TRACE_INFO( "sqlite3_step()" );
246 69 : sqlite_err = sqlite3_step( prepared_statement );
247 69 : if ( SQLITE_ROW != sqlite_err )
248 : {
249 : /* Do not log this incident, the caller may not expect to find a row. */
250 30 : U8_TRACE_INFO_STR( "sqlite3_step did not find a row for uuid", uuid );
251 30 : result |= U8_ERROR_NOT_FOUND;
252 : }
253 :
254 69 : if ( SQLITE_ROW == sqlite_err )
255 : {
256 39 : result |= data_classifier_init( out_classifier,
257 39 : sqlite3_column_int64( prepared_statement, RESULT_CLASSIFIER_ID_COLUMN ),
258 39 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_MAIN_TYPE_COLUMN ),
259 39 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_STEREOTYPE_COLUMN ),
260 39 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_NAME_COLUMN ),
261 39 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_DESCRIPTION_COLUMN ),
262 39 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_X_ORDER_COLUMN ),
263 39 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_Y_ORDER_COLUMN ),
264 39 : sqlite3_column_int( prepared_statement, RESULT_CLASSIFIER_LIST_ORDER_COLUMN ),
265 39 : (const char*) sqlite3_column_text( prepared_statement, RESULT_CLASSIFIER_UUID_COLUMN )
266 : );
267 :
268 39 : data_classifier_trace( out_classifier );
269 :
270 39 : sqlite_err = sqlite3_step( prepared_statement );
271 39 : if ( SQLITE_DONE != sqlite_err )
272 : {
273 0 : U8_LOG_ERROR_INT( "sqlite3_step not done yet:", sqlite_err );
274 0 : result |= U8_ERROR_DB_STRUCTURE;
275 : }
276 : }
277 : }
278 :
279 69 : U8_TRACE_END_ERR( result );
280 69 : return result;
281 : }
282 :
283 5 : u8_error_t data_database_classifier_reader_get_all_classifiers( data_database_classifier_reader_t *this_,
284 : bool hierarchical,
285 : data_classifier_iterator_t *io_classifier_iterator
286 : )
287 : {
288 5 : U8_TRACE_BEGIN();
289 5 : assert( NULL != io_classifier_iterator );
290 5 : u8_error_t result = U8_ERROR_NONE;
291 :
292 5 : sqlite3_stmt *const db_statement
293 : = hierarchical
294 : ? (*this_).statement_classifiers_all_hierarchical
295 : : (*this_).statement_classifiers_all;
296 5 : bool *const borrow_flag
297 : = hierarchical
298 : ? &((*this_).statement_classifiers_all_hierarchical_borrowed)
299 : : &((*this_).statement_classifiers_all_borrowed);
300 : data_database_borrowed_stmt_t sql_statement;
301 5 : data_database_borrowed_stmt_init( &sql_statement, (*this_).database, db_statement, borrow_flag );
302 :
303 5 : result |= data_classifier_iterator_reinit( io_classifier_iterator, sql_statement );
304 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
305 :
306 5 : U8_TRACE_END_ERR( result );
307 5 : return result;
308 : }
309 :
310 : /* ================================ FEATURE ================================ */
311 :
312 : /*!
313 : * \brief predefined search statement to find a feature by id
314 : */
315 : static const char DATA_DATABASE_READER_SELECT_FEATURE_BY_ID[] =
316 : "SELECT id,main_type,classifier_id,key,value,description,list_order,uuid "
317 : "FROM features WHERE id=?;";
318 :
319 : /*!
320 : * \brief predefined search statement to find a feature by uuid
321 : */
322 : static const char DATA_DATABASE_READER_SELECT_FEATURE_BY_UUID[] =
323 : "SELECT id,main_type,classifier_id,key,value,description,list_order,uuid "
324 : "FROM features WHERE uuid=?;";
325 :
326 : /*!
327 : * \brief the column id of the result where this parameter is stored: id
328 : */
329 : static const int RESULT_FEATURE_ID_COLUMN = 0;
330 :
331 : /*!
332 : * \brief the column id of the result where this parameter is stored: main_type
333 : */
334 : static const int RESULT_FEATURE_MAIN_TYPE_COLUMN = 1;
335 :
336 : /*!
337 : * \brief the column id of the result where this parameter is stored: classifier_id
338 : */
339 : static const int RESULT_FEATURE_CLASSIFIER_ID_COLUMN = 2;
340 :
341 : /*!
342 : * \brief the column id of the result where this parameter is stored: key
343 : */
344 : static const int RESULT_FEATURE_KEY_COLUMN = 3;
345 :
346 : /*!
347 : * \brief the column id of the result where this parameter is stored: value
348 : */
349 : static const int RESULT_FEATURE_VALUE_COLUMN = 4;
350 :
351 : /*!
352 : * \brief the column id of the result where this parameter is stored: description
353 : */
354 : static const int RESULT_FEATURE_DESCRIPTION_COLUMN = 5;
355 :
356 : /*!
357 : * \brief the column id of the result where this parameter is stored: list_order
358 : */
359 : static const int RESULT_FEATURE_LIST_ORDER_COLUMN = 6;
360 :
361 : /*!
362 : * \brief the column id of the result where this parameter is stored: uuid
363 : */
364 : static const int RESULT_FEATURE_LIST_UUID_COLUMN = 7;
365 :
366 41 : u8_error_t data_database_classifier_reader_get_feature_by_id ( data_database_classifier_reader_t *this_,
367 : data_row_t id,
368 : data_feature_t *out_feature )
369 : {
370 41 : U8_TRACE_BEGIN();
371 41 : assert( NULL != out_feature );
372 41 : u8_error_t result = U8_ERROR_NONE;
373 : int sqlite_err;
374 : sqlite3_stmt *prepared_statement;
375 :
376 : {
377 41 : prepared_statement = (*this_).statement_feature_by_id;
378 :
379 41 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, id );
380 :
381 41 : U8_TRACE_INFO( "sqlite3_step()" );
382 41 : sqlite_err = sqlite3_step( prepared_statement );
383 41 : if ( SQLITE_ROW != sqlite_err )
384 : {
385 7 : U8_TRACE_INFO_INT( "sqlite3_step did not find a row for id", id );
386 7 : result |= U8_ERROR_DB_STRUCTURE; /* non-existing ids are worse than U8_ERROR_NOT_FOUND */
387 : }
388 :
389 41 : if ( SQLITE_ROW == sqlite_err )
390 : {
391 34 : result |= data_feature_init( out_feature,
392 34 : sqlite3_column_int64( prepared_statement, RESULT_FEATURE_ID_COLUMN ),
393 34 : sqlite3_column_int( prepared_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ),
394 34 : sqlite3_column_int64( prepared_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ),
395 34 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_KEY_COLUMN ),
396 34 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_VALUE_COLUMN ),
397 34 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_DESCRIPTION_COLUMN ),
398 34 : sqlite3_column_int( prepared_statement, RESULT_FEATURE_LIST_ORDER_COLUMN ),
399 34 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_LIST_UUID_COLUMN )
400 : );
401 :
402 34 : data_feature_trace( out_feature );
403 :
404 34 : sqlite_err = sqlite3_step( prepared_statement );
405 34 : if ( SQLITE_DONE != sqlite_err )
406 : {
407 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
408 0 : result |= U8_ERROR_DB_STRUCTURE;
409 : }
410 : }
411 : }
412 :
413 41 : U8_TRACE_END_ERR( result );
414 41 : return result;
415 : }
416 :
417 33 : u8_error_t data_database_classifier_reader_get_feature_by_uuid ( data_database_classifier_reader_t *this_,
418 : const char *uuid,
419 : data_feature_t *out_feature )
420 : {
421 33 : U8_TRACE_BEGIN();
422 33 : assert( NULL != uuid );
423 33 : assert( NULL != out_feature );
424 33 : u8_error_t result = U8_ERROR_NONE;
425 : int sqlite_err;
426 : sqlite3_stmt *prepared_statement;
427 :
428 : {
429 33 : prepared_statement = (*this_).statement_feature_by_uuid;
430 :
431 33 : result |= data_database_classifier_reader_private_bind_text_to_statement( this_, prepared_statement, uuid );
432 :
433 33 : U8_TRACE_INFO( "sqlite3_step()" );
434 33 : sqlite_err = sqlite3_step( prepared_statement );
435 33 : if ( SQLITE_ROW != sqlite_err )
436 : {
437 : /* Do not log this incident, the caller may not expect to find a row. */
438 26 : U8_TRACE_INFO_STR( "sqlite3_step did not find a row for uuid", uuid );
439 26 : result |= U8_ERROR_NOT_FOUND;
440 : }
441 :
442 33 : if ( SQLITE_ROW == sqlite_err )
443 : {
444 7 : result |= data_feature_init( out_feature,
445 7 : sqlite3_column_int64( prepared_statement, RESULT_FEATURE_ID_COLUMN ),
446 7 : sqlite3_column_int( prepared_statement, RESULT_FEATURE_MAIN_TYPE_COLUMN ),
447 7 : sqlite3_column_int64( prepared_statement, RESULT_FEATURE_CLASSIFIER_ID_COLUMN ),
448 7 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_KEY_COLUMN ),
449 7 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_VALUE_COLUMN ),
450 7 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_DESCRIPTION_COLUMN ),
451 7 : sqlite3_column_int( prepared_statement, RESULT_FEATURE_LIST_ORDER_COLUMN ),
452 7 : (const char*) sqlite3_column_text( prepared_statement, RESULT_FEATURE_LIST_UUID_COLUMN )
453 : );
454 :
455 7 : data_feature_trace( out_feature );
456 :
457 7 : sqlite_err = sqlite3_step( prepared_statement );
458 7 : if ( SQLITE_DONE != sqlite_err )
459 : {
460 0 : U8_LOG_ERROR_INT( "sqlite3_step not done yet:", sqlite_err );
461 0 : result |= U8_ERROR_DB_STRUCTURE;
462 : }
463 : }
464 : }
465 :
466 33 : U8_TRACE_END_ERR( result );
467 33 : return result;
468 : }
469 :
470 25 : u8_error_t data_database_classifier_reader_get_features_by_classifier_id ( data_database_classifier_reader_t *this_,
471 : data_row_t classifier_id,
472 : data_feature_iterator_t *io_feature_iterator )
473 : {
474 25 : U8_TRACE_BEGIN();
475 25 : assert( NULL != io_feature_iterator );
476 25 : u8_error_t result = U8_ERROR_NONE;
477 :
478 25 : sqlite3_stmt *const prepared_statement = (*this_).statement_features_by_classifier_id;
479 25 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, classifier_id );
480 :
481 : data_database_borrowed_stmt_t sql_statement;
482 25 : data_database_borrowed_stmt_init( &sql_statement,
483 : (*this_).database,
484 : prepared_statement,
485 : &((*this_).statement_features_by_classifier_id_borrowed)
486 : );
487 25 : result |= data_feature_iterator_reinit( io_feature_iterator, sql_statement );
488 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
489 :
490 25 : U8_TRACE_END_ERR( result );
491 25 : return result;
492 : }
493 :
494 8 : u8_error_t data_database_classifier_reader_get_features_by_diagram_id ( data_database_classifier_reader_t *this_,
495 : data_row_t diagram_id,
496 : data_feature_iterator_t *io_feature_iterator )
497 : {
498 8 : U8_TRACE_BEGIN();
499 8 : assert( NULL != io_feature_iterator );
500 8 : u8_error_t result = U8_ERROR_NONE;
501 :
502 8 : sqlite3_stmt *const prepared_statement = (*this_).statement_features_by_diagram_id;
503 8 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, diagram_id );
504 :
505 : data_database_borrowed_stmt_t sql_statement;
506 8 : data_database_borrowed_stmt_init( &sql_statement,
507 : (*this_).database,
508 : prepared_statement,
509 : &((*this_).statement_features_by_diagram_id_borrowed)
510 : );
511 8 : result |= data_feature_iterator_reinit( io_feature_iterator, sql_statement );
512 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
513 :
514 8 : U8_TRACE_END_ERR( result );
515 8 : return result;
516 : }
517 :
518 : /* ================================ RELATIONSHIP ================================ */
519 :
520 : /*!
521 : * \brief predefined search statement to find a relationship by id
522 : */
523 : static const char DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_ID[] =
524 : "SELECT id,main_type,from_classifier_id,to_classifier_id,stereotype,name,description,list_order,"
525 : "from_feature_id,to_feature_id,uuid "
526 : "FROM relationships WHERE id=?;";
527 :
528 : /*!
529 : * \brief predefined search statement to find a relationship by uuid
530 : */
531 : static const char DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_UUID[] =
532 : "SELECT id,main_type,from_classifier_id,to_classifier_id,stereotype,name,description,list_order,"
533 : "from_feature_id,to_feature_id,uuid "
534 : "FROM relationships WHERE uuid=?;";
535 :
536 : /*!
537 : * \brief the column id of the result where this parameter is stored: id
538 : */
539 : static const int RESULT_RELATIONSHIP_ID_COLUMN = 0;
540 :
541 : /*!
542 : * \brief the column id of the result where this parameter is stored: main_type
543 : */
544 : static const int RESULT_RELATIONSHIP_MAIN_TYPE_COLUMN = 1;
545 :
546 : /*!
547 : * \brief the column id of the result where this parameter is stored: from_classifier_id
548 : */
549 : static const int RESULT_RELATIONSHIP_FROM_CLASSIFIER_ID_COLUMN = 2;
550 :
551 : /*!
552 : * \brief the column id of the result where this parameter is stored: to_classifier_id
553 : */
554 : static const int RESULT_RELATIONSHIP_TO_CLASSIFIER_ID_COLUMN = 3;
555 :
556 : /*!
557 : * \brief the column id of the result where this parameter is stored: name
558 : */
559 : static const int RESULT_RELATIONSHIP_STEREOTYPE_COLUMN = 4;
560 :
561 : /*!
562 : * \brief the column id of the result where this parameter is stored: name
563 : */
564 : static const int RESULT_RELATIONSHIP_NAME_COLUMN = 5;
565 :
566 : /*!
567 : * \brief the column id of the result where this parameter is stored: description
568 : */
569 : static const int RESULT_RELATIONSHIP_DESCRIPTION_COLUMN = 6;
570 :
571 : /*!
572 : * \brief the column id of the result where this parameter is stored: list_order
573 : */
574 : static const int RESULT_RELATIONSHIP_LIST_ORDER_COLUMN = 7;
575 :
576 : /*!
577 : * \brief the column id of the result where this parameter is stored: from_feature_id
578 : */
579 : static const int RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN = 8;
580 :
581 : /*!
582 : * \brief the column id of the result where this parameter is stored: to_feature_id
583 : */
584 : static const int RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN = 9;
585 :
586 : /*!
587 : * \brief the column id of the result where this parameter is stored: uuid
588 : */
589 : static const int RESULT_RELATIONSHIP_UUID_COLUMN = 10;
590 :
591 31 : u8_error_t data_database_classifier_reader_get_relationship_by_id ( data_database_classifier_reader_t *this_,
592 : data_row_t id,
593 : data_relationship_t *out_relationship )
594 : {
595 31 : U8_TRACE_BEGIN();
596 31 : assert( NULL != out_relationship );
597 31 : u8_error_t result = U8_ERROR_NONE;
598 : int sqlite_err;
599 : sqlite3_stmt *prepared_statement;
600 :
601 : {
602 31 : prepared_statement = (*this_).statement_relationship_by_id;
603 :
604 31 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, id );
605 :
606 31 : U8_TRACE_INFO( "sqlite3_step()" );
607 31 : sqlite_err = sqlite3_step( prepared_statement );
608 31 : if ( SQLITE_ROW != sqlite_err )
609 : {
610 10 : U8_TRACE_INFO_INT( "sqlite3_step did not find a row for id", id );
611 10 : result |= U8_ERROR_DB_STRUCTURE; /* non-existing ids are worse than U8_ERROR_NOT_FOUND */
612 : }
613 :
614 31 : if ( SQLITE_ROW == sqlite_err )
615 : {
616 21 : result |= data_relationship_init( out_relationship,
617 21 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_ID_COLUMN ),
618 21 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_CLASSIFIER_ID_COLUMN ),
619 21 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN ),
620 21 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_CLASSIFIER_ID_COLUMN ),
621 21 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN ),
622 21 : sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_MAIN_TYPE_COLUMN ),
623 21 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_STEREOTYPE_COLUMN ),
624 21 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_NAME_COLUMN ),
625 21 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_DESCRIPTION_COLUMN ),
626 21 : sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_LIST_ORDER_COLUMN ),
627 21 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_UUID_COLUMN )
628 : );
629 21 : if ( SQLITE_NULL == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN ) )
630 : {
631 9 : data_relationship_set_from_feature_row ( out_relationship, DATA_ROW_VOID );
632 : }
633 21 : if ( SQLITE_NULL == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN ) )
634 : {
635 13 : data_relationship_set_to_feature_row ( out_relationship, DATA_ROW_VOID );
636 : }
637 :
638 21 : data_relationship_trace( out_relationship );
639 :
640 21 : sqlite_err = sqlite3_step( prepared_statement );
641 21 : if ( SQLITE_DONE != sqlite_err )
642 : {
643 0 : U8_LOG_ERROR_INT( "sqlite3_step failed:", sqlite_err );
644 0 : result |= U8_ERROR_DB_STRUCTURE;
645 : }
646 : }
647 : }
648 :
649 31 : U8_TRACE_END_ERR( result );
650 31 : return result;
651 : }
652 :
653 10 : u8_error_t data_database_classifier_reader_get_relationship_by_uuid ( data_database_classifier_reader_t *this_,
654 : const char *uuid,
655 : data_relationship_t *out_relationship )
656 : {
657 10 : U8_TRACE_BEGIN();
658 10 : assert( NULL != uuid );
659 10 : assert( NULL != out_relationship );
660 10 : u8_error_t result = U8_ERROR_NONE;
661 : int sqlite_err;
662 : sqlite3_stmt *prepared_statement;
663 :
664 : {
665 10 : prepared_statement = (*this_).statement_relationship_by_uuid;
666 :
667 10 : result |= data_database_classifier_reader_private_bind_text_to_statement( this_, prepared_statement, uuid );
668 :
669 10 : U8_TRACE_INFO( "sqlite3_step()" );
670 10 : sqlite_err = sqlite3_step( prepared_statement );
671 10 : if ( SQLITE_ROW != sqlite_err )
672 : {
673 : /* Do not log this incident, the caller may not expect to find a row. */
674 8 : U8_TRACE_INFO_STR( "sqlite3_step did not find a row for uuid", uuid );
675 8 : result |= U8_ERROR_NOT_FOUND;
676 : }
677 :
678 10 : if ( SQLITE_ROW == sqlite_err )
679 : {
680 2 : result |= data_relationship_init( out_relationship,
681 2 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_ID_COLUMN ),
682 2 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_CLASSIFIER_ID_COLUMN ),
683 2 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN ),
684 2 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_CLASSIFIER_ID_COLUMN ),
685 2 : sqlite3_column_int64( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN ),
686 2 : sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_MAIN_TYPE_COLUMN ),
687 2 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_STEREOTYPE_COLUMN ),
688 2 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_NAME_COLUMN ),
689 2 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_DESCRIPTION_COLUMN ),
690 2 : sqlite3_column_int( prepared_statement, RESULT_RELATIONSHIP_LIST_ORDER_COLUMN ),
691 2 : (const char*) sqlite3_column_text( prepared_statement, RESULT_RELATIONSHIP_UUID_COLUMN )
692 : );
693 2 : if ( SQLITE_NULL == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_FROM_FEATURE_ID_COLUMN ) )
694 : {
695 1 : data_relationship_set_from_feature_row ( out_relationship, DATA_ROW_VOID );
696 : }
697 2 : if ( SQLITE_NULL == sqlite3_column_type( prepared_statement, RESULT_RELATIONSHIP_TO_FEATURE_ID_COLUMN ) )
698 : {
699 1 : data_relationship_set_to_feature_row ( out_relationship, DATA_ROW_VOID );
700 : }
701 :
702 2 : data_relationship_trace( out_relationship );
703 :
704 2 : sqlite_err = sqlite3_step( prepared_statement );
705 2 : if ( SQLITE_DONE != sqlite_err )
706 : {
707 0 : U8_LOG_ERROR_INT( "sqlite3_step not done yet:", sqlite_err );
708 0 : result |= U8_ERROR_DB_STRUCTURE;
709 : }
710 : }
711 : }
712 :
713 10 : U8_TRACE_END_ERR( result );
714 10 : return result;
715 : }
716 :
717 47 : u8_error_t data_database_classifier_reader_get_relationships_by_classifier_id ( data_database_classifier_reader_t *this_,
718 : data_row_t classifier_id,
719 : data_relationship_iterator_t *io_relationship_iterator )
720 : {
721 47 : U8_TRACE_BEGIN();
722 47 : assert( NULL != io_relationship_iterator );
723 47 : u8_error_t result = U8_ERROR_NONE;
724 :
725 47 : sqlite3_stmt *const prepared_statement = (*this_).statement_relationships_by_classifier_id;
726 47 : result |= data_database_classifier_reader_private_bind_two_ids_to_statement( this_, prepared_statement, classifier_id, classifier_id );
727 :
728 : data_database_borrowed_stmt_t sql_statement;
729 47 : data_database_borrowed_stmt_init( &sql_statement,
730 : (*this_).database,
731 : prepared_statement,
732 : &((*this_).statement_relationships_by_classifier_id_borrowed)
733 : );
734 47 : result |= data_relationship_iterator_reinit( io_relationship_iterator, sql_statement );
735 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
736 :
737 47 : U8_TRACE_END_ERR( result );
738 47 : return result;
739 : }
740 :
741 16 : u8_error_t data_database_classifier_reader_get_relationships_by_feature_id ( data_database_classifier_reader_t *this_,
742 : data_row_t feature_id,
743 : data_relationship_iterator_t *io_relationship_iterator )
744 : {
745 16 : U8_TRACE_BEGIN();
746 16 : assert( NULL != io_relationship_iterator );
747 16 : u8_error_t result = U8_ERROR_NONE;
748 :
749 16 : sqlite3_stmt *const prepared_statement = (*this_).statement_relationships_by_feature_id;
750 16 : result |= data_database_classifier_reader_private_bind_two_ids_to_statement( this_, prepared_statement, feature_id, feature_id );
751 :
752 : data_database_borrowed_stmt_t sql_statement;
753 16 : data_database_borrowed_stmt_init( &sql_statement,
754 : (*this_).database,
755 : prepared_statement,
756 : &((*this_).statement_relationships_by_feature_id_borrowed)
757 : );
758 16 : result |= data_relationship_iterator_reinit( io_relationship_iterator, sql_statement );
759 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
760 :
761 16 : U8_TRACE_END_ERR( result );
762 16 : return result;
763 : }
764 :
765 8 : u8_error_t data_database_classifier_reader_get_relationships_by_diagram_id ( data_database_classifier_reader_t *this_,
766 : data_row_t diagram_id,
767 : data_relationship_iterator_t *io_relationship_iterator )
768 : {
769 8 : U8_TRACE_BEGIN();
770 8 : assert( NULL != io_relationship_iterator );
771 8 : u8_error_t result = U8_ERROR_NONE;
772 :
773 8 : sqlite3_stmt *const prepared_statement = (*this_).statement_relationships_by_diagram_id;
774 8 : result |= data_database_classifier_reader_private_bind_id_to_statement( this_, prepared_statement, diagram_id );
775 :
776 : data_database_borrowed_stmt_t sql_statement;
777 8 : data_database_borrowed_stmt_init( &sql_statement,
778 : (*this_).database,
779 : prepared_statement,
780 : &((*this_).statement_relationships_by_diagram_id_borrowed)
781 : );
782 8 : result |= data_relationship_iterator_reinit( io_relationship_iterator, sql_statement );
783 : /* do not destroy sql_statement; the object is transferred to the iterator and consumed there. */
784 :
785 8 : U8_TRACE_END_ERR( result );
786 8 : return result;
787 : }
788 :
789 : /* ================================ private ================================ */
790 :
791 112 : u8_error_t data_database_classifier_reader_private_open ( data_database_classifier_reader_t *this_ )
792 : {
793 112 : U8_TRACE_BEGIN();
794 112 : u8_error_t result = U8_ERROR_NONE;
795 :
796 : {
797 112 : result |= data_database_prepare_statement( (*this_).database,
798 : DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_ID,
799 : sizeof( DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_ID ),
800 : &((*this_).statement_classifier_by_id)
801 : );
802 :
803 112 : result |= data_database_prepare_statement( (*this_).database,
804 : DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_UUID,
805 : sizeof( DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_UUID ),
806 : &((*this_).statement_classifier_by_uuid)
807 : );
808 :
809 112 : result |= data_database_prepare_statement( (*this_).database,
810 : DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_NAME,
811 : sizeof( DATA_DATABASE_READER_SELECT_CLASSIFIER_BY_NAME ),
812 : &((*this_).statement_classifier_by_name)
813 : );
814 :
815 112 : result |= data_database_prepare_statement( (*this_).database,
816 : DATA_CLASSIFIER_ITERATOR_SELECT_ALL,
817 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
818 : &((*this_).statement_classifiers_all)
819 : );
820 112 : (*this_).statement_classifiers_all_borrowed = false;
821 :
822 112 : result |= data_database_prepare_statement( (*this_).database,
823 : DATA_CLASSIFIER_ITERATOR_SELECT_ALL_HIERARCHICAL,
824 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
825 : &((*this_).statement_classifiers_all_hierarchical)
826 : );
827 112 : (*this_).statement_classifiers_all_hierarchical_borrowed = false;
828 :
829 112 : result |= data_database_prepare_statement( (*this_).database,
830 : DATA_DATABASE_READER_SELECT_FEATURE_BY_ID,
831 : sizeof( DATA_DATABASE_READER_SELECT_FEATURE_BY_ID ),
832 : &((*this_).statement_feature_by_id)
833 : );
834 :
835 112 : result |= data_database_prepare_statement( (*this_).database,
836 : DATA_DATABASE_READER_SELECT_FEATURE_BY_UUID,
837 : sizeof( DATA_DATABASE_READER_SELECT_FEATURE_BY_UUID ),
838 : &((*this_).statement_feature_by_uuid)
839 : );
840 :
841 112 : result |= data_database_prepare_statement( (*this_).database,
842 : DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_CLASSIFIER_ID,
843 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
844 : &((*this_).statement_features_by_classifier_id)
845 : );
846 112 : (*this_).statement_features_by_classifier_id_borrowed = false;
847 :
848 112 : result |= data_database_prepare_statement( (*this_).database,
849 : DATA_FEATURE_ITERATOR_SELECT_FEATURES_BY_DIAGRAM_ID,
850 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
851 : &((*this_).statement_features_by_diagram_id)
852 : );
853 112 : (*this_).statement_features_by_diagram_id_borrowed = false;
854 :
855 112 : result |= data_database_prepare_statement( (*this_).database,
856 : DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_ID,
857 : sizeof( DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_ID ),
858 : &((*this_).statement_relationship_by_id)
859 : );
860 :
861 112 : result |= data_database_prepare_statement( (*this_).database,
862 : DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_UUID,
863 : sizeof( DATA_DATABASE_READER_SELECT_RELATIONSHIP_BY_UUID ),
864 : &((*this_).statement_relationship_by_uuid)
865 : );
866 :
867 112 : result |= data_database_prepare_statement( (*this_).database,
868 : DATA_RELATIONSHIP_ITERATOR_SELECT_RELATIONSHIPS_BY_CLASSIFIER_ID,
869 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
870 : &((*this_).statement_relationships_by_classifier_id)
871 : );
872 112 : (*this_).statement_relationships_by_classifier_id_borrowed = false;
873 :
874 112 : result |= data_database_prepare_statement( (*this_).database,
875 : DATA_RELATIONSHIP_ITERATOR_SELECT_RELATIONSHIPS_BY_FEATURE_ID,
876 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
877 : &((*this_).statement_relationships_by_feature_id)
878 : );
879 112 : (*this_).statement_relationships_by_feature_id_borrowed = false;
880 :
881 112 : result |= data_database_prepare_statement( (*this_).database,
882 : DATA_RELATIONSHIP_ITERATOR_SELECT_RELATIONSHIPS_BY_DIAGRAM_ID,
883 : DATA_DATABASE_SQL_LENGTH_AUTO_DETECT,
884 : &((*this_).statement_relationships_by_diagram_id)
885 : );
886 112 : (*this_).statement_relationships_by_diagram_id_borrowed = false;
887 :
888 112 : if ( result != U8_ERROR_NONE )
889 : {
890 0 : U8_LOG_ERROR( "A prepared statement could not be prepared." );
891 : }
892 : }
893 :
894 112 : U8_TRACE_END_ERR(result);
895 112 : return result;
896 : }
897 :
898 112 : u8_error_t data_database_classifier_reader_private_close ( data_database_classifier_reader_t *this_ )
899 : {
900 112 : U8_TRACE_BEGIN();
901 112 : u8_error_t result = U8_ERROR_NONE;
902 :
903 : {
904 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_classifier_by_id );
905 112 : (*this_).statement_classifier_by_id = NULL;
906 :
907 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_classifier_by_name );
908 112 : (*this_).statement_classifier_by_name = NULL;
909 :
910 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_classifier_by_uuid );
911 112 : (*this_).statement_classifier_by_uuid = NULL;
912 :
913 112 : assert( (*this_).statement_classifiers_all_borrowed == false );
914 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_classifiers_all );
915 112 : (*this_).statement_classifiers_all = NULL;
916 :
917 112 : assert( (*this_).statement_classifiers_all_hierarchical_borrowed == false );
918 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_classifiers_all_hierarchical );
919 112 : (*this_).statement_classifiers_all_hierarchical = NULL;
920 :
921 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_feature_by_id );
922 112 : (*this_).statement_feature_by_id = NULL;
923 :
924 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_feature_by_uuid );
925 112 : (*this_).statement_feature_by_uuid = NULL;
926 :
927 112 : assert( (*this_).statement_features_by_classifier_id_borrowed == false );
928 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_features_by_classifier_id );
929 112 : (*this_).statement_features_by_classifier_id = NULL;
930 :
931 112 : assert( (*this_).statement_features_by_diagram_id_borrowed == false );
932 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_features_by_diagram_id );
933 112 : (*this_).statement_features_by_diagram_id = NULL;
934 :
935 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_relationship_by_id );
936 112 : (*this_).statement_relationship_by_id = NULL;
937 :
938 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_relationship_by_uuid );
939 112 : (*this_).statement_relationship_by_uuid = NULL;
940 :
941 112 : assert( (*this_).statement_relationships_by_classifier_id_borrowed == false );
942 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_relationships_by_classifier_id );
943 112 : (*this_).statement_relationships_by_classifier_id = NULL;
944 :
945 112 : assert( (*this_).statement_relationships_by_feature_id_borrowed == false );
946 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_relationships_by_feature_id );
947 112 : (*this_).statement_relationships_by_feature_id = NULL;
948 :
949 112 : assert( (*this_).statement_relationships_by_diagram_id_borrowed == false );
950 112 : result |= data_database_finalize_statement( (*this_).database, (*this_).statement_relationships_by_diagram_id );
951 112 : (*this_).statement_relationships_by_diagram_id = NULL;
952 : }
953 :
954 112 : U8_TRACE_END_ERR(result);
955 112 : return result;
956 : }
957 :
958 :
959 : /*
960 : Copyright 2016-2026 Andreas Warnke
961 :
962 : Licensed under the Apache License, Version 2.0 (the "License");
963 : you may not use this file except in compliance with the License.
964 : You may obtain a copy of the License at
965 :
966 : http://www.apache.org/licenses/LICENSE-2.0
967 :
968 : Unless required by applicable law or agreed to in writing, software
969 : distributed under the License is distributed on an "AS IS" BASIS,
970 : WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
971 : See the License for the specific language governing permissions and
972 : limitations under the License.
973 : */
|