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

Revision 675, 24.6 KB checked in by jls17, 5 years ago (diff)
  • moved the new classes from lists/ARListHelpers.cpp into it's own files in the support directory
  • removed some of the code duplication in UTF8StringList
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 = new CARFieldListServer(schemaIndex);
377                srvFieldList->LoadFromServer(); // TODO: maybe check if successfully loaded
378                srvFieldList->Sort();
379                fieldLists.push_back(srvFieldList);
380        }
381
382        // last, load vuis
383        vuiLists.reserve(count);
384
385        for (unsigned int schemaIndex = 0; schemaIndex < count; ++schemaIndex)
386        {
387                CARVUIListServer *srvVuiList = new CARVUIListServer(schemaIndex);
388                srvVuiList->LoadFromServer(); // TODO: maybe check if successfully loaded
389                srvVuiList->Sort();
390                vuiLists.push_back(srvVuiList);
391        }
392
393        missingFieldReferences.resize(count);
394        if (count > 0)
395                memset(&missingFieldReferences[0], 0, sizeof(MissingReferenceList*) * count);
396
397        // reserve reference lists
398        activeLinks.resize(count);
399        filters.resize(count);
400        escalations.resize(count);
401        alGuides.resize(count);
402        fltGuides.resize(count);
403        packLists.resize(count);
404        webservices.resize(count);
405
406        // Sort
407        Sort();
408
409        return funcResult;
410}
411
412void CARSchemaList::InitDatabaseDetails()
413{
414        schemaDbValues.resize(names.numItems);
415        if (names.numItems > 0)
416                memset(&schemaDbValues[0], 0, sizeof(ARSchemaDbValues) * schemaDbValues.size());
417}
418
419void CARSchemaList::LoadDatabaseDetails()
420{
421        ARStatusList    status;
422        CARInside*      arIn = CARInside::GetInstance();
423        unsigned int    numMatches = 0;
424        ARValueListList valueList;
425
426        // if there was no schema loaded, we skip this method
427        if (names.numItems == 0) return;
428
429        InitDatabaseDetails();
430
431        // the needed columns in arschema are available since 7.1 only
432        if (arIn->CompareServerVersion(7,1) < 0)
433                return;
434
435        ARZeroMemory(&valueList);
436       
437        SchemaDbQueryBuilder queryBuilder;
438        bool keepGettingNextChunk = true;
439
440        while (keepGettingNextChunk)
441        {
442                keepGettingNextChunk = false;
443                int result = ARGetListSQL(&arIn->arControl, const_cast<char*>(queryBuilder.GetNextQuery()), 0, &valueList, &numMatches, &status);
444
445                if (result == AR_RETURN_OK || result == AR_RETURN_WARNING)
446                {
447                        StoreDatabaseDetails(valueList);
448
449                        if (valueList.numItems > 0 && status.numItems > 0 && status.statusList[0].messageNum == AR_WARN_MAX_ENTRIES_RETRIEVED)
450                        {
451                                unsigned int lastReceiveSchemaId = 0;
452                                SchemaDbQueryBuilder::TryReadSchemaId(valueList.valueListList[valueList.numItems-1], lastReceiveSchemaId);
453                                queryBuilder.SetLastReceivedSchemaId(lastReceiveSchemaId);
454                                queryBuilder.SetMaxRetrieve(valueList.numItems);
455                                keepGettingNextChunk = true;
456                        }
457                        FreeARValueListList(&valueList, false);
458                        FreeARStatusList(&status, false);
459                }
460                else
461                {
462                        cout << BuildMessageAndFreeStatus(status);
463                }
464        }
465}
466
467void CARSchemaList::StoreDatabaseDetails(ARValueListList &valueList)
468{
469        if (valueList.numItems == 0) return;
470
471        for (unsigned int valPos = 0; valPos < valueList.numItems; ++valPos)
472        {
473                ARValueList& row = valueList.valueListList[valPos];
474               
475                if (row.numItems < SchemaDbQueryBuilder::ExpectedColumnCount() || row.valueList[1].dataType != AR_DATA_TYPE_CHAR)
476                        continue;
477               
478                int idx = TryFindSchemaInNameList(row.valueList[1].u.charVal);
479                if (idx < 0) // not found
480                {
481                        continue;
482                }
483                StoreSingleDatabaseRow(row, idx);
484        }
485}
486
487int CARSchemaList::TryFindSchemaInNameList(const char* schemaName)
488{
489        int idx = 0;
490        for (; idx < static_cast<int>(names.numItems); ++idx)
491        {
492                if (strncmp(names.nameList[idx], schemaName, AR_MAX_NAME_SIZE) == 0)
493                        return idx;
494        }
495        return -1;
496}
497
498void CARSchemaList::StoreSingleDatabaseRow(ARValueList &row, int storeToSchemaIndex)
499{
500        if (storeToSchemaIndex < 0 || storeToSchemaIndex >= static_cast<int>(schemaDbValues.size())) return;
501
502        ARSchemaDbValues &dbValues = schemaDbValues[storeToSchemaIndex];
503
504        SchemaDbQueryBuilder::TryReadSchemaId(row, dbValues.schemaId);
505        SchemaDbQueryBuilder::TryReadSchemaView(row, dbValues.viewName);
506        SchemaDbQueryBuilder::TryReadSchemaShView(row, dbValues.shViewName);
507}
508
509void CARSchemaList::Reserve(unsigned int size)
510{
511        if (internalListState != CARSchemaList::EMPTY) throw AppException("object isnt reusable!", "SchemaList");
512
513        sortedList.reserve(size);
514        missingFieldReferences.resize(size);
515
516        names.numItems = 0;
517        names.nameList = new ARNameType[size];
518
519        compounds.numItems = 0;
520        compounds.compoundSchema = new ARCompoundSchema[size];
521
522        permissions.numItems = 0;
523        permissions.permissionList = new ARPermissionList[size];
524
525        subAdmins.numItems = 0;
526        subAdmins.internalIdListList = new ARInternalIdList[size];
527
528        resultFields.numItems = 0;
529        resultFields.listFieldList = new AREntryListFieldList[size];
530
531        sortings.numItems = 0;
532        sortings.sortListList = new ARSortList[size];
533
534        indexes.numItems = 0;
535        indexes.indexListList = new ARIndexList[size];
536
537        archives.numItems = 0;
538        archives.archiveInfoList = new ARArchiveInfoStruct[size];
539
540        audits.numItems = 0;
541        audits.auditInfoList = new ARAuditInfoStruct[size];
542
543        defaultVUIs.numItems = 0;
544        defaultVUIs.nameList = new ARNameType[size];
545
546        helpTexts.numItems = 0;
547        helpTexts.stringList = new char*[size];
548
549        changedTimes.numItems = 0;
550        changedTimes.timestampList = new ARTimestamp[size];
551
552        owners.numItems = 0;
553        owners.nameList = new ARAccessNameType[size];
554
555        changedUsers.numItems = 0;
556        changedUsers.nameList = new ARAccessNameType[size];
557
558        changeDiary.numItems = 0;
559        changeDiary.stringList = new char*[size];
560
561        objProps.numItems = 0;
562        objProps.propsList = new ARPropList[size];
563       
564        appRefNames.reserve(size);
565        fieldLists.reserve(size);
566        vuiLists.reserve(size);
567
568        // reserve reference lists
569        references.resize(size);
570        activeLinks.resize(size);
571        filters.resize(size);
572        escalations.resize(size);
573        alGuides.resize(size);
574        fltGuides.resize(size);
575        packLists.resize(size);
576        webservices.resize(size);
577
578        InitDatabaseDetails();
579
580        reservedSize = size;
581        internalListState = CARSchemaList::INTERNAL_ALLOC;
582}
583
584int CARSchemaList::AddSchemaFromXML(ARXMLParsedStream &stream, const char* schemaName, unsigned int *outDocVersion)
585{
586        if (internalListState != CARSchemaList::INTERNAL_ALLOC) throw AppException("illegal usage!", "SchemaList");
587        if (names.numItems >= reservedSize) return -1;
588        if (outDocVersion != NULL) *outDocVersion = 0;
589       
590        CARInside* arIn = CARInside::GetInstance();
591        ARNameType appBlockName; appBlockName[0] = 0;
592        ARStatusList status;
593
594        unsigned int arDocVersion = 0;
595        unsigned int index = names.numItems;
596        strncpy(names.nameList[index], schemaName, AR_MAX_NAME_SIZE);   // copy name over
597        names.nameList[index][AR_MAX_NAME_SIZE] = 0;
598
599        // create the sub-lists
600        CARFieldListXML* fldList = new CARFieldListXML();
601        CARVUIListXML* vuiList = new CARVUIListXML();
602
603        if (ARGetSchemaFromXML(&arIn->arControl,
604                &stream,
605                names.nameList[index],
606                appBlockName,
607                &compounds.compoundSchema[index],
608                &permissions.permissionList[index],
609                &subAdmins.internalIdListList[index],
610                &resultFields.listFieldList[index],
611                &sortings.sortListList[index],
612                &indexes.indexListList[index],
613                &archives.archiveInfoList[index],
614                &audits.auditInfoList[index],
615                defaultVUIs.nameList[index],
616                NULL, // next fieldid
617                NULL,   // core version
618                NULL,   // upgrade version
619                &fldList->fieldInfo,
620                &vuiList->vuiList,
621                owners.nameList[index],
622                changedUsers.nameList[index],
623                &changedTimes.timestampList[index],
624                &helpTexts.stringList[index],
625                &changeDiary.stringList[index],
626                &objProps.propsList[index],
627                &arDocVersion,
628                &status) == AR_RETURN_OK)
629        {
630                ++names.numItems;
631                ++compounds.numItems;
632                ++permissions.numItems;
633                ++subAdmins.numItems;
634                ++resultFields.numItems;
635                ++sortings.numItems;
636                ++indexes.numItems;
637                ++archives.numItems;
638                ++audits.numItems;
639                ++defaultVUIs.numItems;
640                ++helpTexts.numItems;
641                ++changedTimes.numItems;
642                ++owners.numItems;
643                ++changedUsers.numItems;
644                ++changeDiary.numItems;
645                ++objProps.numItems;
646
647                // signal finished loading to sub-objects
648                fldList->FinishLoading();
649                vuiList->FinishLoading();
650
651                fieldLists.push_back(fldList);
652                vuiLists.push_back(vuiList);
653
654                sortedList.push_back(index);
655                appRefNames.push_back("");
656
657                if (outDocVersion != NULL) *outDocVersion = arDocVersion;
658
659                return index;
660        }
661        else
662        {
663                cerr << BuildMessageAndFreeStatus(status);
664                return -1;
665        }
666}
667
668int CARSchemaList::Find(const char* name)
669{
670        CMapType::const_iterator it = searchList.find(string(name));
671        if (it == searchList.end()) return -1;
672        return it->second;
673}
674
675void CARSchemaList::Sort()
676{
677        if (GetCount() > 0)
678        {
679#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
680                NormalizeNameListForSorting(names, objProps);
681#endif
682
683                IndexSorter indexSorter(CARInside::GetInstance()->appConfig.bUseUtf8);
684                indexSorter.SortBy(names).Sort(sortedList);
685
686                if (GetCount() > schemaDbValues.size())
687                        InitDatabaseDetails();
688        }
689
690        // setup lookup map
691        if (!searchList.empty()) searchList.clear();
692        for (unsigned int i = 0; i < sortedList.size(); ++i)
693        {
694                searchList[string(names.nameList[sortedList[i]])] = i;
695        }
696
697#if AR_CURRENT_API_VERSION >= AR_API_VERSION_764
698        NormalizeNameListToRealNames(names, objProps);
699#endif
700}
701
702void CARSchemaList::SchemaAddMissingFieldReference(unsigned int index, int fieldId, const CRefItem &refItem)
703{
704        if (fieldId <= 0) return;       // dont add keyword references (like $-6$ ($SERVER$))
705        MissingReferenceList* list = missingFieldReferences[sortedList[index]];
706        if (list == NULL)
707        {
708                list = new MissingReferenceList();
709                missingFieldReferences[sortedList[index]] = list;
710        }
711
712        if (list->size() > 0)
713        {
714                // check if reference is already there
715                MissingReferenceList::iterator curIt = list->begin();
716                MissingReferenceList::iterator endIt = list->end();
717                for (; curIt != endIt; ++curIt)
718                        if (curIt->first == fieldId && 
719                                curIt->second == refItem) return;
720        }
721        list->push_back(MissingReferenceItem(fieldId, refItem));
722}
723
724const CARSchemaList::MissingReferenceList* CARSchemaList::SchemaGetMissingReferences(unsigned int index)
725{
726        return missingFieldReferences[sortedList[index]];
727}
728
729void CARSchemaList::SortReferences()
730{
731        size_t listCount = activeLinks.size();
732        for (unsigned int schemaIndex = 0; schemaIndex < listCount; ++schemaIndex)
733        {
734                std::sort(activeLinks[schemaIndex].begin(), activeLinks[schemaIndex].end());
735                std::sort(    filters[schemaIndex].begin(),     filters[schemaIndex].end());
736                std::sort(escalations[schemaIndex].begin(), escalations[schemaIndex].end());
737                std::sort(   alGuides[schemaIndex].begin(),    alGuides[schemaIndex].end());
738                std::sort(  fltGuides[schemaIndex].begin(),   fltGuides[schemaIndex].end());
739                std::sort(  packLists[schemaIndex].begin(),   packLists[schemaIndex].end());
740                std::sort(webservices[schemaIndex].begin(), webservices[schemaIndex].end());
741        }
742}
743
744void CARSchemaList::SchemaAddFilter(unsigned int index, const CARFilter &filter)
745{
746        filters[index].push_back(filter.GetInsideId());
747}
748
749void CARSchemaList::SchemaAddActiveLink(unsigned int index, const CARActiveLink &actlink)
750{
751        activeLinks[index].push_back(actlink.GetInsideId());
752}
753
754void CARSchemaList::SchemaAddEscalation(unsigned int index, const CAREscalation &escalation)
755{
756        escalations[index].push_back(escalation.GetInsideId());
757}
758
759void CARSchemaList::SchemaAddActLinkGuide(unsigned int index, const CARContainer &alGuide)
760{
761        alGuides[index].push_back(alGuide.GetInsideId());
762}
763
764void CARSchemaList::SchemaAddFilterGuide(unsigned int index, const CARContainer &fltGuide)
765{
766        fltGuides[index].push_back(fltGuide.GetInsideId());
767}
768
769void CARSchemaList::SchemaAddPackingList(unsigned int index, const CARContainer &packList)
770{
771        packLists[index].push_back(packList.GetInsideId());
772}
773
774void CARSchemaList::SchemaAddWebservice(unsigned int index, const CARContainer &webservice)
775{
776        webservices[index].push_back(webservice.GetInsideId());
777}
778
779void CARSchemaList::AddReference(unsigned int index, const CRefItem &refItem)
780{
781        references[sortedList[index]].push_back(refItem);
782}
783
784bool CARSchemaList::ReferenceExists(unsigned int index, const CRefItem &refItem)
785{
786        ReferenceList::iterator curIt = references[sortedList[index]].begin();
787        ReferenceList::iterator endIt = references[sortedList[index]].end();
788
789        for (; curIt != endIt; ++curIt)
790        {
791                if (*curIt == refItem)
792                        return true;
793        }
794        return false;
795}
796
797const CARSchemaList::ReferenceList& CARSchemaList::GetReferences(unsigned int index)
798{
799        return references[sortedList[index]];
800}
801
802void CARSchemaList::AddOverlayOrCustom(unsigned int index)
803{
804        overlayAndCustomList.push_back(index);
805}
806
807const CARSchemaList::ObjectRefList& CARSchemaList::GetOverlayAndCustomWorkflow()
808{
809        return overlayAndCustomList;
810}
Note: See TracBrowser for help on using the repository browser.