source: branches/work_320/lists/ARSchemaList.cpp @ 679

Revision 679, 24.9 KB checked in by jls17, 5 years ago (diff)
  • fixed some memory leaks in case memory allocation fails in ARFieldList.cpp and ARSchemaList.cpp
  • small changes to the initialization of the crash handler
Line 
1//Copyright (C) 2010 John Luthgers | jls17
2//
3//This file is part of ARInside.
4//
5//    ARInside is free software: you can redistribute it and/or modify
6//    it under the terms of the GNU General Public License as published by
7//    the Free Software Foundation, version 2 of the License.
8//
9//    ARInside is distributed in the hope that it will be useful,
10//    but WITHOUT ANY WARRANTY; without even the implied warranty of
11//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12//    GNU General Public License for more details.
13//
14//    You should have received a copy of the GNU General Public License
15//    along with ARInside.  If not, see <http://www.gnu.org/licenses/>.
16
17#include "stdafx.h"
18#include "ARListHelpers.h"
19#include "ARSchemaList.h"
20#include "../ARInside.h"
21#include "../core/ARStatusList.h"
22#include "../output/WebUtil.h"
23#include "BlackList.h"
24#include "support/IndexSorter.h"
25#include "support/SchemaDbQueryBuilder.h"
26
27CARSchemaList::CARSchemaList(void)
28{
29        internalListState = CARSchemaList::EMPTY;
30        reservedSize = 0;
31        names.numItems = 0;
32        apiBug = false;
33
34        ARZeroMemory(&names);
35        ARZeroMemory(&compounds);
36        ARZeroMemory(&permissions);
37        ARZeroMemory(&subAdmins);
38        ARZeroMemory(&resultFields);
39        ARZeroMemory(&sortings);
40        ARZeroMemory(&indexes);
41        ARZeroMemory(&archives);
42        ARZeroMemory(&audits);
43        ARZeroMemory(&defaultVUIs);
44        ARZeroMemory(&helpTexts);
45        ARZeroMemory(&changedTimes);
46        ARZeroMemory(&owners);
47        ARZeroMemory(&changedUsers);
48        ARZeroMemory(&changeDiary);
49        ARZeroMemory(&objProps);
50}
51
52CARSchemaList::~CARSchemaList(void)
53{
54        if (internalListState == CARSchemaList::INTERNAL_ALLOC)
55        {
56                try
57                {
58                        delete[] names.nameList;
59                        delete[] compounds.compoundSchema;
60                        delete[] permissions.permissionList;
61                        delete[] subAdmins.internalIdListList;
62                        delete[] resultFields.listFieldList;
63                        delete[] sortings.sortListList;
64                        delete[] indexes.indexListList;
65                        delete[] archives.archiveInfoList;
66                        delete[] audits.auditInfoList;
67                        delete[] defaultVUIs.nameList;
68                        delete[] helpTexts.stringList;
69                        delete[] changedTimes.timestampList;
70                        delete[] owners.nameList;
71                        delete[] changedUsers.nameList;
72                        delete[] changeDiary.stringList;
73                        delete[] objProps.propsList;
74                }
75                catch (...)
76                {
77                }
78        }
79        else if (internalListState == CARSchemaList::ARAPI_ALLOC)
80        {               
81                try
82                {
83                        FreeARNameList(&names,false);
84                        FreeARCompoundSchemaList(&compounds,false);
85                        FreeARPermissionListList(&permissions,false);
86                        FreeARInternalIdListList(&subAdmins,false);
87                        FreeAREntryListFieldListList(&resultFields,false);
88                        FreeARSortListList(&sortings,false);
89                        FreeARIndexListList(&indexes,false);
90                        FreeARArchiveInfoList(&archives,false);
91                        FreeARAuditInfoList(&audits,false);
92                        FreeARNameList(&defaultVUIs,false);
93                        FreeARTextStringList(&helpTexts,false);
94                        if (!apiBug) // <APIBUG>
95                                FreeARTimestampList(&changedTimes,false);
96                        FreeARAccessNameList(&owners,false);
97                        FreeARAccessNameList(&changedUsers,false);
98                        FreeARTextStringList(&changeDiary,false);
99                        FreeARPropListList(&objProps,false);
100
101                        for_each(fieldLists.begin(), fieldLists.end(), DeletePointer<CARFieldList>());
102                        for_each(vuiLists.begin(), vuiLists.end(), DeletePointer<CARVUIList>());
103                }
104                catch (...)
105                {
106
107                }
108        }
109}
110
111bool CARSchemaList::LoadFromServer()
112{
113        ARBooleanList   schemaExists;
114        ARStatusList    status;
115        CARInside*      arIn = CARInside::GetInstance();
116        ARNameList*     objectsToLoad = NULL;
117        ARNameList      objectNames;
118        unsigned int    originalObjectNameCount = 0;
119        bool            funcResult = false;
120
121        memset(&schemaExists, 0, sizeof(schemaExists));
122        memset(&status, 0, sizeof(status));
123
124        // if the blacklist contains schemas, we should first load all names from the
125        // server and remove those that are contained in the blacklist. after that call
126        // ARGetMultipleSchemas to retrieve just the needed objects.
127        if (arIn->blackList.GetCountOf(ARREF_SCHEMA) > 0)
128        {
129                memset(&objectNames, 0, sizeof(objectNames));
130
131                if (ARGetListSchema(&arIn->arControl, 0, AR_LIST_SCHEMA_ALL | AR_HIDDEN_INCREMENT, NULL, NULL, NULL, &objectNames, &status) == AR_RETURN_OK)
132                {
133                        originalObjectNameCount = objectNames.numItems;
134                        arIn->blackList.Exclude(ARREF_SCHEMA, &objectNames);
135                        objectsToLoad = &objectNames;
136                }
137                else
138                        cerr << BuildMessageAndFreeStatus(status);
139        }
140
141        // ok, now retrieve all informations of the schemas we need
142        if (!arIn->appConfig.slowObjectLoading && ARGetMultipleSchemas(&arIn->arControl,
143                0, // changed since
144                NULL, // schema type list
145                objectsToLoad,
146                NULL, // field id list
147                &schemaExists,
148                &names,
149                &compounds,
150                NULL, // schema inheritance list ... reserved for future use
151#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
152                NULL, // groupListList // TODO: support static inherited permissions
153#endif
154                &permissions,
155                &subAdmins,
156                &resultFields,
157                &sortings,
158                &indexes,
159                &archives,
160                &audits,
161                &defaultVUIs,
162                &helpTexts,
163                &changedTimes,
164                &owners,
165                &changedUsers,
166                &changeDiary,
167                &objProps,
168                &status) == AR_RETURN_OK)
169        {
170                FreeARBooleanList(&schemaExists, false);
171                internalListState = CARSchemaList::ARAPI_ALLOC;
172                funcResult = true;
173
174
175                // <APIBUG>
176                //
177                // This is just a workarround for a bug in ARAPI 7.6.03/7.6.04
178                //
179                // Notes: ClientAPI 7.6.04 (32bit) => Server 7.6.04 (64bit) working
180                //        ClientAPI 7.5.00 (32bit) => Server 7.6.04 (64bit) failed
181                //        ClientAPI 7.6.04 (32bit) => Server 7.5.00 (32bit) failed
182                //        ClientAPI 7.6.04 (64bit) => Server 7.6.04 (64bit) working
183                //        ClientAPI 7.6.04 (64bit) => Server 7.5.00 (32bit) failed
184                // You can use the driver utility to reproduce the error. (Sequence: init, log, ssp, ver, gms => crash)
185                if (changedTimes.numItems == 0 && names.numItems > 0)
186                {
187                        // <APIBUG-WORKAROUND>
188                        // ok, as a workaround we can try to load the timestamps via direct sql.
189                        // There is a "but" ...
190                        //  if program is compiled using 7.6.03 or lower and is run against 7.6.04 server with some overlaid
191                        //  schemas, those schemas show wrong timestamps (they show timestamps from their base objects). Why?
192                        //  The overlay of form "User" is named "User__o" in arschema table. Loading the form via the API
193                        //  returns the form as "User". So we get different names for the same schema and are "not able" to
194                        //  match the timestamps together. (It might be possible, but because those API-versions doesn't know
195                        //  anything about overlays, i don't want to start dealing with overlays in a workaround.)
196                        //  In my mind, showing the timestamp of the base form is better than no timestamps at all.
197
198                        unsigned int numMatches = 0;
199                        ARValueListList valueList;
200                        ARZeroMemory(&valueList);
201
202                        if (ARGetListSQL(&arIn->arControl, (char*)"select name, timestamp from arschema", 0, &valueList, &numMatches, &status) == AR_RETURN_OK)
203                        {
204                                if (numMatches > 0)
205                                {
206                                        ARTimestamp* timestamps = new ARTimestamp[names.numItems];
207                                        unsigned int foundTimes = 0;
208                                        memset(timestamps, 0, sizeof(ARTimestamp) * names.numItems);
209
210                                        for (unsigned int i = 0; i < names.numItems; ++i)
211                                        {
212                                                for (unsigned int valPos = 0; valPos < valueList.numItems; ++valPos)
213                                                {
214                                                        ARValueList& row = valueList.valueListList[valPos];
215                                                       
216                                                        if (row.numItems != 2 || row.valueList[0].dataType != AR_DATA_TYPE_CHAR || row.valueList[1].dataType != AR_DATA_TYPE_INTEGER)
217                                                                continue;
218
219                                                        if (strncmp(names.nameList[i], row.valueList[0].u.charVal, AR_MAX_NAME_SIZE) == 0)
220                                                        {
221                                                                timestamps[i] = row.valueList[1].u.intVal;
222                                                                foundTimes++;
223                                                        }
224                                                }
225                                        }
226
227                                        if (foundTimes > 0)
228                                        {
229                                                cout << "NOTE: ARAPI bug detected. Schema timestamps loaded via direct sql!" << endl;
230                                                changedTimes.timestampList = timestamps;
231                                                changedTimes.numItems = names.numItems;
232                                                apiBug = true;
233                                        }
234                                }
235                        }
236                        else
237                        {
238                                cout << BuildMessageAndFreeStatus(status);
239                        }
240                        // </APIBUG-WORKAROUND>
241
242                        if (changedTimes.numItems == 0)
243                        {
244                                cout << "NOTE: ARAPI bug detected. Modify timestamps of schemas will not be available!" << endl;
245
246                                changedTimes.timestampList = new ARTimestamp[names.numItems];
247                                changedTimes.numItems = names.numItems;
248                                memset(changedTimes.timestampList, 0, sizeof(ARTimestamp) * names.numItems);
249                                apiBug = true;
250                        }
251                }
252                // </APIBUG>
253        }
254        else
255        {
256                cerr << BuildMessageAndFreeStatus(status);
257
258                // ok, fallback to slow data retrieval
259                // this could be necessaray if there is a corrupt schema that keeps us from getting all schemas at once
260                if (!arIn->appConfig.slowObjectLoading)
261                        cout << "WARN: switching to slow schema loading!" << endl;
262
263                // first check if schema names are already loaded
264                if (objectsToLoad == NULL)
265                {
266                        // no filter names loaded ... now get all names from server
267                        memset(&objectNames, 0, sizeof(objectNames));
268
269                        if (ARGetListSchema(&arIn->arControl, 0, AR_LIST_SCHEMA_ALL | AR_HIDDEN_INCREMENT, NULL, NULL, NULL, &objectNames, &status) == AR_RETURN_OK)
270                        {
271                                originalObjectNameCount = objectNames.numItems;
272                                objectsToLoad = &objectNames;
273                        }
274                        else
275                                cerr << BuildMessageAndFreeStatus(status);
276                }
277
278                if (objectsToLoad != NULL && objectsToLoad->numItems > 0)
279                {
280                        // allocate needed size for internal lists
281                        this->Reserve(objectsToLoad->numItems);
282
283                        // use a separate counter for the store index, because if a schema can't be loaded, this index is not incremented
284                        unsigned int curListPos = 0; 
285
286                        // now load each schema
287                        for (unsigned int i=0; i < objectsToLoad->numItems; ++i)
288                        {
289                                LOG << "Loading Schema: " << objectsToLoad->nameList[i] << " ";
290
291                                strncpy(names.nameList[curListPos], objectsToLoad->nameList[i], AR_MAX_NAME_SIZE);
292                                names.nameList[curListPos][AR_MAX_NAME_SIZE] = 0;
293
294                                if(ARGetSchema(&arIn->arControl,
295                                        names.nameList[curListPos],
296                                        &compounds.compoundSchema[curListPos],
297                                        NULL,
298#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
299                                        NULL, // groupList // TODO: support static inherited permissions
300#endif
301                                        &permissions.permissionList[curListPos],
302                                        &subAdmins.internalIdListList[curListPos],
303                                        &resultFields.listFieldList[curListPos],
304                                        &sortings.sortListList[curListPos],
305                                        &indexes.indexListList[curListPos],
306                                        &archives.archiveInfoList[curListPos],
307                                        &audits.auditInfoList[curListPos],
308                                        defaultVUIs.nameList[curListPos],
309                                        &helpTexts.stringList[curListPos],
310                                        &changedTimes.timestampList[curListPos],
311                                        owners.nameList[curListPos],
312                                        changedUsers.nameList[curListPos],
313                                        &changeDiary.stringList[curListPos],
314                                        &objProps.propsList[curListPos],
315                                        &status) == AR_RETURN_OK)
316                                {
317                                        LOG << " (InsideID: " << curListPos << ") [OK]" << endl;                                               
318                                        curListPos++;
319
320                                        FreeARStatusList(&status, false);
321                                }
322                                else
323                                        cerr << "Failed to load '" << names.nameList[curListPos] << "' : " << BuildMessageAndFreeStatus(status);
324                        }
325
326                        // now update list counts
327                        names.numItems = curListPos;
328                        compounds.numItems = curListPos;
329                        permissions.numItems = curListPos;
330                        subAdmins.numItems = curListPos;
331                        resultFields.numItems = curListPos;
332                        sortings.numItems = curListPos;
333                        indexes.numItems = curListPos;
334                        archives.numItems = curListPos;
335                        audits.numItems = curListPos;
336                        defaultVUIs.numItems = curListPos;
337                        helpTexts.numItems = curListPos;
338                        changedTimes.numItems = curListPos;
339                        owners.numItems = curListPos;
340                        changedUsers.numItems = curListPos;
341                        changeDiary.numItems = curListPos;
342                        objProps.numItems = curListPos;
343
344                        // zero schemas to load? This shouldn't happen, but if it happens, then it might be correct
345                        if (curListPos > 0 || objectsToLoad->numItems == 0)
346                                funcResult = true;
347                }
348        }
349
350        LoadDatabaseDetails();
351
352        // check if we have to clean up the name list
353        if (originalObjectNameCount > 0)
354        {
355                objectNames.numItems = originalObjectNameCount;
356                FreeARNameList(&objectNames, false);
357        }
358
359        if (funcResult)
360        {
361                sortedList.reserve(names.numItems);
362                for (unsigned int i=0; i<names.numItems; ++i)
363                {
364                        appRefNames.push_back("");
365                        sortedList.push_back(i);
366                }
367                references.resize(names.numItems);
368        }
369
370        // next, loading fields...     
371        unsigned int count = names.numItems;
372        fieldLists.reserve(count);
373
374        for (unsigned int schemaIndex = 0; schemaIndex < count; ++schemaIndex)
375        {
376                CARFieldListServer *srvFieldList = NULL;
377                try
378                {
379                        srvFieldList = new CARFieldListServer(schemaIndex);
380                        srvFieldList->LoadFromServer(); // TODO: maybe check if successfully loaded
381                        srvFieldList->Sort();
382                }
383                catch (exception &e)
384                {
385                        cerr << "FATAL: loading fields for '" << SchemaGetName(schemaIndex) << "' failed with: " << e.what() << endl;
386                        if (srvFieldList != NULL) { delete srvFieldList; }
387                        srvFieldList = new CARFieldListServer(schemaIndex);
388                }
389                fieldLists.push_back(srvFieldList);
390        }
391
392        // last, load vuis
393        vuiLists.reserve(count);
394
395        for (unsigned int schemaIndex = 0; schemaIndex < count; ++schemaIndex)
396        {
397                CARVUIListServer *srvVuiList = new CARVUIListServer(schemaIndex);
398                srvVuiList->LoadFromServer(); // TODO: maybe check if successfully loaded
399                srvVuiList->Sort();
400                vuiLists.push_back(srvVuiList);
401        }
402
403        missingFieldReferences.resize(count);
404        if (count > 0)
405                memset(&missingFieldReferences[0], 0, sizeof(MissingReferenceList*) * count);
406
407        // reserve reference lists
408        activeLinks.resize(count);
409        filters.resize(count);
410        escalations.resize(count);
411        alGuides.resize(count);
412        fltGuides.resize(count);
413        packLists.resize(count);
414        webservices.resize(count);
415
416        // Sort
417        Sort();
418
419        return funcResult;
420}
421
422void CARSchemaList::InitDatabaseDetails()
423{
424        schemaDbValues.resize(names.numItems);
425        if (names.numItems > 0)
426                memset(&schemaDbValues[0], 0, sizeof(ARSchemaDbValues) * schemaDbValues.size());
427}
428
429void CARSchemaList::LoadDatabaseDetails()
430{
431        ARStatusList    status;
432        CARInside*      arIn = CARInside::GetInstance();
433        unsigned int    numMatches = 0;
434        ARValueListList valueList;
435
436        // if there was no schema loaded, we skip this method
437        if (names.numItems == 0) return;
438
439        InitDatabaseDetails();
440
441        // the needed columns in arschema are available since 7.1 only
442        if (arIn->CompareServerVersion(7,1) < 0)
443                return;
444
445        ARZeroMemory(&valueList);
446       
447        SchemaDbQueryBuilder queryBuilder;
448        bool keepGettingNextChunk = true;
449
450        while (keepGettingNextChunk)
451        {
452                keepGettingNextChunk = false;
453                int result = ARGetListSQL(&arIn->arControl, const_cast<char*>(queryBuilder.GetNextQuery()), 0, &valueList, &numMatches, &status);
454
455                if (result == AR_RETURN_OK || result == AR_RETURN_WARNING)
456                {
457                        StoreDatabaseDetails(valueList);
458
459                        if (valueList.numItems > 0 && status.numItems > 0 && status.statusList[0].messageNum == AR_WARN_MAX_ENTRIES_RETRIEVED)
460                        {
461                                unsigned int lastReceiveSchemaId = 0;
462                                SchemaDbQueryBuilder::TryReadSchemaId(valueList.valueListList[valueList.numItems-1], lastReceiveSchemaId);
463                                queryBuilder.SetLastReceivedSchemaId(lastReceiveSchemaId);
464                                queryBuilder.SetMaxRetrieve(valueList.numItems);
465                                keepGettingNextChunk = true;
466                        }
467                        FreeARValueListList(&valueList, false);
468                        FreeARStatusList(&status, false);
469                }
470                else
471                {
472                        cout << BuildMessageAndFreeStatus(status);
473                }
474        }
475}
476
477void CARSchemaList::StoreDatabaseDetails(ARValueListList &valueList)
478{
479        if (valueList.numItems == 0) return;
480
481        for (unsigned int valPos = 0; valPos < valueList.numItems; ++valPos)
482        {
483                ARValueList& row = valueList.valueListList[valPos];
484               
485                if (row.numItems < SchemaDbQueryBuilder::ExpectedColumnCount() || row.valueList[1].dataType != AR_DATA_TYPE_CHAR)
486                        continue;
487               
488                int idx = TryFindSchemaInNameList(row.valueList[1].u.charVal);
489                if (idx < 0) // not found
490                {
491                        continue;
492                }
493                StoreSingleDatabaseRow(row, idx);
494        }
495}
496
497int CARSchemaList::TryFindSchemaInNameList(const char* schemaName)
498{
499        int idx = 0;
500        for (; idx < static_cast<int>(names.numItems); ++idx)
501        {
502                if (strncmp(names.nameList[idx], schemaName, AR_MAX_NAME_SIZE) == 0)
503                        return idx;
504        }
505        return -1;
506}
507
508void CARSchemaList::StoreSingleDatabaseRow(ARValueList &row, int storeToSchemaIndex)
509{
510        if (storeToSchemaIndex < 0 || storeToSchemaIndex >= static_cast<int>(schemaDbValues.size())) return;
511
512        ARSchemaDbValues &dbValues = schemaDbValues[storeToSchemaIndex];
513
514        SchemaDbQueryBuilder::TryReadSchemaId(row, dbValues.schemaId);
515        SchemaDbQueryBuilder::TryReadSchemaView(row, dbValues.viewName);
516        SchemaDbQueryBuilder::TryReadSchemaShView(row, dbValues.shViewName);
517}
518
519void CARSchemaList::Reserve(unsigned int size)
520{
521        if (internalListState != CARSchemaList::EMPTY) throw AppException("object isnt reusable!", "SchemaList");
522
523        sortedList.reserve(size);
524        missingFieldReferences.resize(size);
525
526        names.numItems = 0;
527        names.nameList = new ARNameType[size];
528
529        compounds.numItems = 0;
530        compounds.compoundSchema = new ARCompoundSchema[size];
531
532        permissions.numItems = 0;
533        permissions.permissionList = new ARPermissionList[size];
534
535        subAdmins.numItems = 0;
536        subAdmins.internalIdListList = new ARInternalIdList[size];
537
538        resultFields.numItems = 0;
539        resultFields.listFieldList = new AREntryListFieldList[size];
540
541        sortings.numItems = 0;
542        sortings.sortListList = new ARSortList[size];
543
544        indexes.numItems = 0;
545        indexes.indexListList = new ARIndexList[size];
546
547        archives.numItems = 0;
548        archives.archiveInfoList = new ARArchiveInfoStruct[size];
549
550        audits.numItems = 0;
551        audits.auditInfoList = new ARAuditInfoStruct[size];
552
553        defaultVUIs.numItems = 0;
554        defaultVUIs.nameList = new ARNameType[size];
555
556        helpTexts.numItems = 0;
557        helpTexts.stringList = new char*[size];
558
559        changedTimes.numItems = 0;
560        changedTimes.timestampList = new ARTimestamp[size];
561
562        owners.numItems = 0;
563        owners.nameList = new ARAccessNameType[size];
564
565        changedUsers.numItems = 0;
566        changedUsers.nameList = new ARAccessNameType[size];
567
568        changeDiary.numItems = 0;
569        changeDiary.stringList = new char*[size];
570
571        objProps.numItems = 0;
572        objProps.propsList = new ARPropList[size];
573       
574        appRefNames.reserve(size);
575        fieldLists.reserve(size);
576        vuiLists.reserve(size);
577
578        // reserve reference lists
579        references.resize(size);
580        activeLinks.resize(size);
581        filters.resize(size);
582        escalations.resize(size);
583        alGuides.resize(size);
584        fltGuides.resize(size);
585        packLists.resize(size);
586        webservices.resize(size);
587
588        InitDatabaseDetails();
589
590        reservedSize = size;
591        internalListState = CARSchemaList::INTERNAL_ALLOC;
592}
593
594int CARSchemaList::AddSchemaFromXML(ARXMLParsedStream &stream, const char* schemaName, unsigned int *outDocVersion)
595{
596        if (internalListState != CARSchemaList::INTERNAL_ALLOC) throw AppException("illegal usage!", "SchemaList");
597        if (names.numItems >= reservedSize) return -1;
598        if (outDocVersion != NULL) *outDocVersion = 0;
599       
600        CARInside* arIn = CARInside::GetInstance();
601        ARNameType appBlockName; appBlockName[0] = 0;
602        ARStatusList status;
603
604        unsigned int arDocVersion = 0;
605        unsigned int index = names.numItems;
606        strncpy(names.nameList[index], schemaName, AR_MAX_NAME_SIZE);   // copy name over
607        names.nameList[index][AR_MAX_NAME_SIZE] = 0;
608
609        // create the sub-lists
610        CARFieldListXML* fldList = new CARFieldListXML();
611        CARVUIListXML* vuiList = new CARVUIListXML();
612
613        if (ARGetSchemaFromXML(&arIn->arControl,
614                &stream,
615                names.nameList[index],
616                appBlockName,
617                &compounds.compoundSchema[index],
618                &permissions.permissionList[index],
619                &subAdmins.internalIdListList[index],
620                &resultFields.listFieldList[index],
621                &sortings.sortListList[index],
622                &indexes.indexListList[index],
623                &archives.archiveInfoList[index],
624                &audits.auditInfoList[index],
625                defaultVUIs.nameList[index],
626                NULL, // next fieldid
627                NULL,   // core version
628                NULL,   // upgrade version
629                &fldList->fieldInfo,
630                &vuiList->vuiList,
631                owners.nameList[index],
632                changedUsers.nameList[index],
633                &changedTimes.timestampList[index],
634                &helpTexts.stringList[index],
635                &changeDiary.stringList[index],
636                &objProps.propsList[index],
637                &arDocVersion,
638                &status) == AR_RETURN_OK)
639        {
640                ++names.numItems;
641                ++compounds.numItems;
642                ++permissions.numItems;
643                ++subAdmins.numItems;
644                ++resultFields.numItems;
645                ++sortings.numItems;
646                ++indexes.numItems;
647                ++archives.numItems;
648                ++audits.numItems;
649                ++defaultVUIs.numItems;
650                ++helpTexts.numItems;
651                ++changedTimes.numItems;
652                ++owners.numItems;
653                ++changedUsers.numItems;
654                ++changeDiary.numItems;
655                ++objProps.numItems;
656
657                // signal finished loading to sub-objects
658                fldList->FinishLoading();
659                vuiList->FinishLoading();
660
661                fieldLists.push_back(fldList);
662                vuiLists.push_back(vuiList);
663
664                sortedList.push_back(index);
665                appRefNames.push_back("");
666
667                if (outDocVersion != NULL) *outDocVersion = arDocVersion;
668
669                return index;
670        }
671        else
672        {
673                cerr << BuildMessageAndFreeStatus(status);
674                return -1;
675        }
676}
677
678int CARSchemaList::Find(const char* name)
679{
680        CMapType::const_iterator it = searchList.find(string(name));
681        if (it == searchList.end()) return -1;
682        return it->second;
683}
684
685void CARSchemaList::Sort()
686{
687        if (GetCount() > 0)
688        {
689#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
690                NormalizeNameListForSorting(names, objProps);
691#endif
692
693                IndexSorter indexSorter(CARInside::GetInstance()->appConfig.bUseUtf8);
694                indexSorter.SortBy(names).Sort(sortedList);
695
696                if (GetCount() > schemaDbValues.size())
697                        InitDatabaseDetails();
698        }
699
700        // setup lookup map
701        if (!searchList.empty()) searchList.clear();
702        for (unsigned int i = 0; i < sortedList.size(); ++i)
703        {
704                searchList[string(names.nameList[sortedList[i]])] = i;
705        }
706
707#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
708        NormalizeNameListToRealNames(names, objProps);
709#endif
710}
711
712void CARSchemaList::SchemaAddMissingFieldReference(unsigned int index, int fieldId, const CRefItem &refItem)
713{
714        if (fieldId <= 0) return;       // dont add keyword references (like $-6$ ($SERVER$))
715        MissingReferenceList* list = missingFieldReferences[sortedList[index]];
716        if (list == NULL)
717        {
718                list = new MissingReferenceList();
719                missingFieldReferences[sortedList[index]] = list;
720        }
721
722        if (list->size() > 0)
723        {
724                // check if reference is already there
725                MissingReferenceList::iterator curIt = list->begin();
726                MissingReferenceList::iterator endIt = list->end();
727                for (; curIt != endIt; ++curIt)
728                        if (curIt->first == fieldId && 
729                                curIt->second == refItem) return;
730        }
731        list->push_back(MissingReferenceItem(fieldId, refItem));
732}
733
734const CARSchemaList::MissingReferenceList* CARSchemaList::SchemaGetMissingReferences(unsigned int index)
735{
736        return missingFieldReferences[sortedList[index]];
737}
738
739void CARSchemaList::SortReferences()
740{
741        size_t listCount = activeLinks.size();
742        for (unsigned int schemaIndex = 0; schemaIndex < listCount; ++schemaIndex)
743        {
744                std::sort(activeLinks[schemaIndex].begin(), activeLinks[schemaIndex].end());
745                std::sort(    filters[schemaIndex].begin(),     filters[schemaIndex].end());
746                std::sort(escalations[schemaIndex].begin(), escalations[schemaIndex].end());
747                std::sort(   alGuides[schemaIndex].begin(),    alGuides[schemaIndex].end());
748                std::sort(  fltGuides[schemaIndex].begin(),   fltGuides[schemaIndex].end());
749                std::sort(  packLists[schemaIndex].begin(),   packLists[schemaIndex].end());
750                std::sort(webservices[schemaIndex].begin(), webservices[schemaIndex].end());
751        }
752}
753
754void CARSchemaList::SchemaAddFilter(unsigned int index, const CARFilter &filter)
755{
756        filters[index].push_back(filter.GetInsideId());
757}
758
759void CARSchemaList::SchemaAddActiveLink(unsigned int index, const CARActiveLink &actlink)
760{
761        activeLinks[index].push_back(actlink.GetInsideId());
762}
763
764void CARSchemaList::SchemaAddEscalation(unsigned int index, const CAREscalation &escalation)
765{
766        escalations[index].push_back(escalation.GetInsideId());
767}
768
769void CARSchemaList::SchemaAddActLinkGuide(unsigned int index, const CARContainer &alGuide)
770{
771        alGuides[index].push_back(alGuide.GetInsideId());
772}
773
774void CARSchemaList::SchemaAddFilterGuide(unsigned int index, const CARContainer &fltGuide)
775{
776        fltGuides[index].push_back(fltGuide.GetInsideId());
777}
778
779void CARSchemaList::SchemaAddPackingList(unsigned int index, const CARContainer &packList)
780{
781        packLists[index].push_back(packList.GetInsideId());
782}
783
784void CARSchemaList::SchemaAddWebservice(unsigned int index, const CARContainer &webservice)
785{
786        webservices[index].push_back(webservice.GetInsideId());
787}
788
789void CARSchemaList::AddReference(unsigned int index, const CRefItem &refItem)
790{
791        references[sortedList[index]].push_back(refItem);
792}
793
794bool CARSchemaList::ReferenceExists(unsigned int index, const CRefItem &refItem)
795{
796        ReferenceList::iterator curIt = references[sortedList[index]].begin();
797        ReferenceList::iterator endIt = references[sortedList[index]].end();
798
799        for (; curIt != endIt; ++curIt)
800        {
801                if (*curIt == refItem)
802                        return true;
803        }
804        return false;
805}
806
807const CARSchemaList::ReferenceList& CARSchemaList::GetReferences(unsigned int index)
808{
809        return references[sortedList[index]];
810}
811
812void CARSchemaList::AddOverlayOrCustom(unsigned int index)
813{
814        overlayAndCustomList.push_back(index);
815}
816
817const CARSchemaList::ObjectRefList& CARSchemaList::GetOverlayAndCustomWorkflow()
818{
819        return overlayAndCustomList;
820}
Note: See TracBrowser for help on using the repository browser.