source: branches/work_304/doc/DocFieldDetails.cpp @ 405

Revision 405, 36.1 KB checked in by jls17, 6 years ago (diff)
  • changed some of the still existent calls to CARInside::GetSchemaInsideId? and replaced them by lookups via CARSchema
Line 
1//Copyright (C) 2009 Stefan Nerlich | stefan.nerlich@hotmail.com
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 Foobar.  If not, see <http://www.gnu.org/licenses/>.
16
17#include "stdafx.h"
18#include "DocFieldDetails.h"
19#include "DocOverlayHelper.h"
20#include "../util/RefItem.h"
21#include "../core/ARImage.h"
22#include "../core/ARGlobalField.h"
23
24CDocFieldDetails::CDocFieldDetails(unsigned int SchemaInsideId, const CARField& fieldObj, int rootLevel)
25: schema(SchemaInsideId), field(fieldObj)
26{
27}
28
29CDocFieldDetails::~CDocFieldDetails(void)
30{
31}
32
33void CDocFieldDetails::Documentation()
34{
35        try
36        {
37                CPageParams file(PAGE_DETAILS, &this->field);
38                rootLevel = file->GetRootLevel();
39
40                CWebPage webPage(file->GetFileName(), this->field.GetName(), rootLevel, this->pInside->appConfig);
41                CDocOverlayHelper overlayHelper(field, rootLevel);
42
43                int overlayType = field.GetOverlayType();
44                int schemaOverlayType = this->schema.GetOverlayType();
45
46                //ContentHead informations
47                stringstream contHeadStrm;
48                contHeadStrm << CWebUtil::LinkToSchemaIndex(this->rootLevel) << endl;
49                contHeadStrm << MenuSeparator << this->pInside->LinkToSchemaTypeList(this->schema.GetCompound().schemaType, rootLevel) << endl;
50                contHeadStrm << MenuSeparator << CWebUtil::Link(this->schema.GetName(), CPageParams(PAGE_DETAILS, &schema), "", rootLevel) << endl;
51                if (overlayHelper.IsOriginal() || overlayHelper.IsCustom())
52                        contHeadStrm << CAREnum::GetOverlayTypeString(schemaOverlayType);
53                contHeadStrm << MenuSeparator << CAREnum::DataType(this->field.GetDataType()) << " " << CWebUtil::Link("Field",  CPageParams(PAGE_OVERVIEW, AR_STRUCT_ITEM_XML_FIELD, &field), "", rootLevel) << endl;
54                contHeadStrm << MenuSeparator << CWebUtil::ObjName(this->field.GetName()) << endl;
55                contHeadStrm << " (Id: " << this->field.GetFieldId() << ")" << CAREnum::GetOverlayTypeString(overlayType) << endl;
56               
57                webPage.AddContentHead(contHeadStrm.str(), overlayHelper.PlaceOverlayLink());
58                webPage.AddContent(overlayHelper.PlaceOverlaidNotice());
59
60                //Field property table
61                CTable tblFieldprops("commonPropList", "TblObjectList");
62                tblFieldprops.AddColumn(20, "Description");
63                tblFieldprops.AddColumn(80, "Value");
64
65                //Create Mode
66                CTableRow row("cssStdRow");             
67                row.AddCellList("CreateMode", CAREnum::FieldCreateMode(this->field.GetCreateMode()));
68                tblFieldprops.AddRow(row);
69
70                //Option
71                row.AddCellList("Option", CAREnum::FieldOption(this->field.GetOption()));
72                tblFieldprops.AddRow(row);
73
74
75                //Default value         
76                string tmp = this->DefaultValue();
77                if(tmp.empty())
78                        tmp = EmptyValue;
79
80                row.AddCellList("Default Value", tmp);
81                tblFieldprops.AddRow(row);
82
83
84                //Permissions
85                tmp = this->Permisssions();
86                if(tmp.empty())
87                        tmp = EmptyValue;
88
89                row.AddCellList("Permissions", tmp);
90                tblFieldprops.AddRow(row);
91
92
93                //Display Properties
94                tmp = this->DisplayProperties();
95                if(tmp.empty())
96                        tmp = EmptyValue;
97
98                row.AddCellList("Display Properties", tmp);
99                tblFieldprops.AddRow(row);
100
101
102                //Fieldlimits           
103                tmp = this->FieldLimits();
104                if(!tmp.empty())
105                {
106                        row.AddCellList("Field Limits", tmp);
107                        tblFieldprops.AddRow(row);
108                }
109
110                // Field Mapping (for Join, View and Vendor)
111                switch (this->field.GetMapping().fieldType)
112                {
113                case AR_FIELD_JOIN:
114                case AR_FIELD_VIEW:
115                case AR_FIELD_VENDOR:
116                        tmp = this->FieldMapping();
117                        if (!tmp.empty())
118                        {
119                                stringstream rowDescription;
120                                rowDescription << CAREnum::FieldMappingType(this->field.GetMapping().fieldType) << " Information";
121                                row.AddCellList(rowDescription.str(), tmp);
122                                tblFieldprops.AddRow(row);
123                        }
124                        break;
125                }
126
127
128                //Join Form References
129                if(this->schema.GetCompound().schemaType != AR_SCHEMA_DIALOG)
130                {
131                        tmp = this->JoinFormReferences();
132                        if(tmp.empty())
133                                tmp = EmptyValue;
134
135                        row.AddCellList("References to Join-Forms", tmp);
136                        tblFieldprops.AddRow(row);
137                }
138
139                // attached workflow
140                tmp = this->WorkflowAttached();
141                if (!tmp.empty())
142                {
143                        row.AddCellList("Attached Workflow", tmp);
144                        tblFieldprops.AddRow(row);
145                }
146
147                webPage.AddContent(tblFieldprops.ToXHtml());
148
149                //Add Workflow references to page
150                webPage.AddContent(this->WorkflowReferences());
151
152                //History
153                webPage.AddContent(this->pInside->ServerObjectHistory(&this->field, this->rootLevel));
154
155                webPage.SaveInFolder(file->GetPath());
156        }
157        catch(exception& e)
158        {
159                cout << "EXCEPTION field details: " << this->field.GetName() << " in form: " << this->schema.GetName() << " error: " << e.what() << endl;
160        }
161}
162
163string CDocFieldDetails::WorkflowReferences()
164{
165        stringstream strm;
166        strm.str("");
167
168        try
169        {
170                //Field references
171                CTable tblRef("referenceList", "TblObjectList");
172                tblRef.AddColumn(10, "Type");
173                tblRef.AddColumn(45, "Server object");
174                tblRef.AddColumn(5, "Enabled");
175                tblRef.AddColumn(40, "Description");
176
177                const CARField::ReferenceList& list = this->field.GetReferences();
178                CARField::ReferenceList::const_iterator iter = list.begin();
179                CARField::ReferenceList::const_iterator endIt = list.end();
180
181                for (; iter != endIt; ++iter)
182                {
183                        if (iter->GetMessageId() == REFM_FOCUSFIELD || iter->GetMessageId() == REFM_CONTROLFIELD)
184                                continue;
185
186                        CTableRow row("cssStdRow");
187                        row.AddCell(CAREnum::XmlStructItem(iter->GetObjectType()));                             
188                        row.AddCell(this->pInside->LinkToObjByRefItem(*iter, rootLevel));
189
190                        bool hasEnabledFlag;
191                        unsigned int enabled = iter->GetObjectEnabled(hasEnabledFlag);
192
193                        string tmpEnabled = "";
194                        string tmpCssEnabled = "";
195                        if (hasEnabledFlag)
196                        {
197                                tmpEnabled = CAREnum::ObjectEnable(enabled);
198                                if (!enabled) { tmpCssEnabled = "objStatusDisabled"; }
199                        }
200
201                        row.AddCell(CTableCell(tmpEnabled, tmpCssEnabled));
202                        row.AddCell(iter->GetDescription(rootLevel));                           
203                        tblRef.AddRow(row);             
204                }
205
206                int curFieldId = this->field.GetFieldId();
207                if (curFieldId >= 1000000 && curFieldId < 2000000)
208                {
209                        std::list<CARGlobalField>::iterator curIt = this->pInside->globalFieldList.begin();
210                        std::list<CARGlobalField>::iterator endIt = this->pInside->globalFieldList.end();
211                        for (; curIt != endIt; ++curIt)
212                        {
213                                if (curIt->fieldId == curFieldId && curIt->schemaInsideId != field.GetSchema().GetInsideId())
214                                {
215                                        CARField fld(curIt->schemaInsideId, curIt->fieldId);
216
217                                        stringstream strm;
218                                        strm << "Field with same global field id in " << fld.GetSchema().GetURL(rootLevel);
219
220                                        CTableRow row("cssStdRow");
221                                        row.AddCell(CAREnum::XmlStructItem(AR_STRUCT_ITEM_XML_FIELD));                         
222                                        row.AddCell(fld.GetURL(rootLevel));
223                                        row.AddCell(CTableCell(""));
224                                        row.AddCell(strm.str());
225                                        tblRef.AddRow(row);             
226                                }
227                        }
228                }
229
230                stringstream tblDesc;
231                tblDesc << CWebUtil::ImageTag("doc.gif", rootLevel) << "Workflow Reference:";
232
233                tblRef.description = tblDesc.str();
234
235                strm << tblRef;
236        }
237        catch(exception& e)
238        {
239                cout << "EXCEPTION enumerating workflow references for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
240        }       
241
242        return strm.str();
243}
244
245
246
247int CDocFieldDetails::AttachmentFieldGetPool(const CARField& fldObj)
248{
249        try
250        {
251                const ARDisplayInstanceList& dispList = fldObj.GetDisplayInstances();
252                for(unsigned int i=0; i< dispList.numItems; i++)
253                {
254                        ARValueStruct* dParent = CARProplistHelper::Find(dispList.dInstanceList[i].props, AR_DPROP_DISPLAY_PARENT);
255                        if (dParent != NULL && (dParent->dataType == AR_DATA_TYPE_ULONG || dParent->dataType == AR_DATA_TYPE_INTEGER))
256                        {
257                                return dParent->u.intVal;
258                        }
259                }               
260        }
261        catch(exception& e)
262        {
263                cout << "EXCEPTION find attachment field pool of '" << this->field.GetName() << "': " << e.what() << endl;
264        }
265        return 0;
266}
267
268// just a temporary struct for column sorting
269class ColumnWithOrder
270{
271public:
272        ColumnWithOrder(unsigned int theOrder, const CARField& theField) { order = theOrder; field = theField; }
273        unsigned int order;
274        CARField field;
275};
276
277// this is a special class used in the next method for sorting table columns by column ordering
278class SortByColumnOrder
279{
280public:
281        SortByColumnOrder(int schemaIndex) 
282        { 
283                this->schemaIndex = schemaIndex;
284        }
285        bool operator()(const ColumnWithOrder& l, const ColumnWithOrder& r) 
286        {
287                return l.order < r.order;
288        }
289
290private:
291        int schemaIndex;
292};
293
294string CDocFieldDetails::FieldLimits()
295{
296        stringstream strm;
297        strm.str("");
298
299        try
300        {
301                switch(this->field.GetLimits().dataType)
302                {                       
303                case AR_DATA_TYPE_CHAR:
304                        {
305                                const ARCharLimitsStruct& fLimit = this->field.GetLimits().u.charLimits;
306
307                                if(fLimit.charMenu[0] != 0)
308                                {
309                                        strm << "Menu: " << this->pInside->LinkToMenu(fLimit.charMenu, rootLevel) << "<br/>" << endl;
310                                }
311
312                                strm << "Fulltext Option: " << CAREnum::FieldFTOption(fLimit.fullTextOptions) << "<br/>" << endl;
313                                strm << "QBE Match: " << CAREnum::FieldQbeMatch(fLimit.qbeMatchOperation) << "<br/>" << endl;
314                                strm << "Max. Length: " << fLimit.maxLength << "<br/>" << endl;
315
316                                if(fLimit.pattern != NULL && !strcmp(fLimit.pattern, "")==0 )
317                                {
318                                        strm << "Pattern: " << pInside->TextFindFields(fLimit.pattern, "$", schema.GetInsideId(), rootLevel, true, NULL) << "<br/>" << endl;
319                                }
320
321#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
322                                if (pInside->CompareServerVersion(7,5) >= 0)
323                                {
324                                        strm << "Length Unit: " << (fLimit.lengthUnits == 1 ? "Chars" : "Bytes") << "<br/>" << endl;
325                                        strm << "CLOB-Storage: " << CAREnum::StorageOptionForCLOB(fLimit.storageOptionForCLOB) << endl;
326                                }
327#endif
328                        }
329                        break;
330                case AR_DATA_TYPE_ATTACH:
331                        {
332                                const ARAttachLimitsStruct& fLimit = this->field.GetLimits().u.attachLimits;
333                                strm << "Max. Size: " << fLimit.maxSize;
334
335                                int nPoolId = AttachmentFieldGetPool(field);
336
337                                if(nPoolId > 0)
338                                {
339                                        strm << "<br/>Field in Attachment Pool: " << this->pInside->LinkToField(this->schema.GetInsideId(), nPoolId, rootLevel);
340                                }
341                        }
342                        break;
343                case AR_DATA_TYPE_ATTACH_POOL:
344                        {                               
345                                unsigned int fieldCount = schema.GetFields()->GetCount();
346                                for(unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
347                                {
348                                        CARField attachField(schema.GetInsideId(), 0, fieldIndex);
349
350                                        if (attachField.GetDataType() == AR_DATA_TYPE_ATTACH)
351                                        {
352                                                if (AttachmentFieldGetPool(attachField) == field.GetInsideId())
353                                                {
354                                                        strm << "Attachment Field: " << attachField.GetURL(rootLevel) << "<br/>" << endl;
355                                                }
356                                        }
357                                }
358                        }
359                        break;
360                case AR_DATA_TYPE_COLUMN:
361                        {
362                                const ARColumnLimitsStruct& fLimit = this->field.GetLimits().u.columnLimits;
363                                strm << "Column in Table: " << this->pInside->LinkToField(this->schema.GetInsideId(), fLimit.parent, rootLevel) << "<br/>" << endl;
364
365                                //To create a link to the datafield we first must find the source form and the source field of the column
366                                CARField colSourceField; // initialize to unknown field
367                                string colSourceForm;
368
369                                GetColumnSourceField(this->field, colSourceField, &colSourceForm);
370                                int schemaIndex = colSourceField.GetSchema().GetInsideId();
371                                int fieldIndex = fLimit.dataField;
372
373                                strm << "Source Type: " << CAREnum::ColumnDataSourceType(fLimit.dataSource) << "<br/>Source Field: " << this->pInside->LinkToField(schemaIndex, fLimit.dataField, rootLevel);
374                                strm << " In Schema: " << (schemaIndex > -1 ? this->pInside->LinkToSchema(colSourceField.GetSchema().GetInsideId(), rootLevel) : colSourceForm) << "<br/>";
375                               
376                                if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DATA_FIELD)
377                                        strm << "Length: " << fLimit.colLength << "<br/>";
378
379                                strm << endl;
380                        }
381                        break;
382                case AR_DATA_TYPE_CURRENCY:
383                        {
384                                const ARCurrencyLimitsStruct& fLimit = this->field.GetLimits().u.currencyLimits;
385
386                                strm << "Min: " << fLimit.rangeLow << " Max: " << fLimit.rangeHigh;
387                                strm << " Precision: " << fLimit.precision << "<br/>" << endl;                 
388
389                                strm << "Allowable Types:<br/>" << endl;
390
391                                if(fLimit.allowableCurrencies.numItems == 0)
392                                {
393                                        strm << "All Allowable Currency Types allowed<br/>" << endl;
394                                }
395                                else
396                                {
397                                        for(unsigned int i=0; i< fLimit.allowableCurrencies.numItems; i++)
398                                        {
399                                                strm << "Code: " << fLimit.allowableCurrencies.currencyDetailList[i].currencyCode << "<br/>" << endl;
400                                        }                                       
401                                }
402
403                                strm << "<br/>Functional Types:<br/>" << endl;
404                                for(unsigned int i=0; i< fLimit.functionalCurrencies.numItems; i++)
405                                {
406                                        strm << "Code: " << fLimit.functionalCurrencies.currencyDetailList[i].currencyCode << " (" << fLimit.functionalCurrencies.currencyDetailList[i].precision  << ")<br/>" << endl;
407                                }
408                        }
409                        break;
410                case AR_DATA_TYPE_DATE:
411                        {
412                                const ARDateLimitsStruct& fLimit = this->field.GetLimits().u.dateLimits;
413                                strm << "Max. " << fLimit.maxDate << " Min. " << fLimit.minDate << "<br/>" << endl;
414                        }
415                        break;
416                case AR_DATA_TYPE_DECIMAL:
417                        {
418                                const ARDecimalLimitsStruct& fLimit = this->field.GetLimits().u.decimalLimits;
419
420                                strm << "Min: " << fLimit.rangeLow << " Max: " << fLimit.rangeHigh;
421                                strm << " Precision: " << fLimit.precision << "<br/>" << endl;                 
422                        }
423                        break;
424                case AR_DATA_TYPE_DIARY:
425                        {
426                                const ARDiaryLimitsStruct& fLimit = this->field.GetLimits().u.diaryLimits;
427                                strm << "Index For FTS: " << CAREnum::FieldFTOption(fLimit.fullTextOptions) << "<br/>" << endl;                 
428                        }
429                        break;
430                case AR_DATA_TYPE_DISPLAY:
431                        {
432                                const ARDisplayLimits& fLimit = this->field.GetLimits().u.displayLimits;
433                                strm << "Max. Length: " << fLimit.maxLength << "<br/>" << endl; 
434#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
435                                if (pInside->CompareServerVersion(7,5) >= 0)
436                                {
437                                        strm << "Length Unit: " << (fLimit.lengthUnits == 1 ? "Chars" : "Bytes") << "<br/>" << endl;
438                                }
439#endif
440                        }
441                        break;         
442                case AR_DATA_TYPE_ENUM:
443                        {
444                                const AREnumLimitsStruct& fLimit = this->field.GetLimits().u.enumLimits;
445
446                                strm << "List Style: " << CAREnum::EnumStyle(fLimit.listStyle) << "<br/>" << endl;                                             
447                                switch(fLimit.listStyle)
448                                {
449                                case AR_ENUM_STYLE_REGULAR:
450                                        {
451                                                strm << "Items: " << "<br/>" << endl;
452                                                for(unsigned int i=0; i < fLimit.u.regularList.numItems; i++)
453                                                {
454                                                        strm << i << " - " << fLimit.u.regularList.nameList[i] << "<br/>" << endl;
455                                                }
456                                        }
457                                        break;
458                                case AR_ENUM_STYLE_CUSTOM:
459                                        {
460                                                strm << "Items: " << "<br/>" << endl;
461                                                for(unsigned int i=0; i < fLimit.u.customList.numItems; i++)
462                                                {
463                                                        strm << fLimit.u.customList.enumItemList[i].itemNumber << " - " << fLimit.u.customList.enumItemList[i].itemName << "<br/>" << endl;
464                                                }
465                                        }
466                                        break;
467                                case AR_ENUM_STYLE_QUERY:
468                                        {
469                                                strm << "Query enum<br/>" << endl;
470                                        }
471                                        break;
472                                }
473
474                        }
475                        break;
476                case AR_DATA_TYPE_INTEGER:
477                        {
478                                const ARIntegerLimitsStruct& fLimit = this->field.GetLimits().u.intLimits;
479                                strm << "Min: " << fLimit.rangeLow << " Max: " << fLimit.rangeHigh << "<br/>" << endl;
480                        }
481                        break;
482                case AR_DATA_TYPE_BITMASK:
483                        {
484                                const AREnumLimitsStruct& fLimit = this->field.GetLimits().u.maskLimits;
485                                strm << "BitmaskLimit" << "<br/>" << endl;
486
487                        }
488                        break;
489                case AR_DATA_TYPE_REAL:
490                        {
491                                const ARRealLimitsStruct& fLimit = this->field.GetLimits().u.realLimits;
492
493                                strm << "Min: " << fLimit.rangeLow << " Max: " << fLimit.rangeHigh;
494                                strm << " Precision: " << fLimit.precision << "<br/>" << endl;
495
496                        }
497                        break;                 
498                case AR_DATA_TYPE_TABLE:
499                        {
500                                const ARTableLimitsStruct& fLimit = this->field.GetLimits().u.tableLimits;
501                                string tableServer;
502                                string tableSchemaName;
503
504                                strm << "<p>Server: ";
505                                if (fLimit.server[0] == '$' && fLimit.sampleServer[0] != 0)
506                                {
507                                        int fieldId = atoi(&fLimit.server[1]);
508                                        tableServer = fLimit.sampleServer;
509
510                                        strm << "$" << (fieldId < 0 ? CAREnum::Keyword(abs(fieldId)) : pInside->LinkToField(schema.GetInsideId(), fieldId, rootLevel) ) << "$ (Sample Server: " << pInside->LinkToServerInfo(tableServer, rootLevel) << ")";
511
512                                        if (fieldId > 0)
513                                        {
514                                                CRefItem refItem(this->field, REFM_TABLEFIELD_SERVER);
515                                                pInside->AddFieldReference(schema.GetInsideId(), fieldId, refItem);
516                                        }
517                                }
518                                else
519                                {
520                                        strm << this->pInside->LinkToServerInfo(fLimit.server, rootLevel);
521                                }
522                                strm << "<br/>" << endl;
523
524                                strm << "Form: ";;
525                                if (fLimit.schema[0] == '$' && fLimit.sampleSchema[0] != 0)
526                                {
527                                        int fieldId = atoi(&fLimit.schema[1]);
528                                        tableSchemaName = fLimit.sampleSchema;
529
530                                        if (tableSchemaName.compare(AR_CURRENT_SCHEMA_TAG) == 0)
531                                                tableSchemaName = schema.GetARName();
532
533                                        strm << "$" << (fieldId < 0 ? CAREnum::Keyword(abs(fieldId)) : pInside->LinkToField(schema.GetInsideId(), fieldId, rootLevel) ) << "$ (Sample Form: " << pInside->LinkToSchema(tableSchemaName, rootLevel) << ")";
534
535                                        if (fieldId > 0)
536                                        {
537                                                CRefItem refItem(this->field, REFM_TABLEFIELD_FORM);
538                                                pInside->AddFieldReference(schema.GetInsideId(), fieldId, refItem);
539                                        }
540                                }
541                                else
542                                {
543                                        tableSchemaName = fLimit.schema;
544
545                                        if (tableSchemaName.compare(AR_CURRENT_SCHEMA_TAG) == 0)
546                                                tableSchemaName = schema.GetARName();
547
548                                        strm << this->pInside->LinkToSchema(tableSchemaName, rootLevel);
549                                }
550                                strm << "<p/>" << endl;
551
552                                stringstream strmQuery;
553                                if(fLimit.qualifier.operation != AR_COND_OP_NONE)
554                                {               
555                                        CRefItem refItem; // Dont change; reference to nothing, because table field references are already created
556                                        CARQualification arQual(*this->pInside);
557                                        CARSchema tableSchema(tableSchemaName);
558
559                                        arQual.CheckQuery(&fLimit.qualifier, refItem, 0, schema.GetInsideId(), tableSchema.GetInsideId(), strmQuery, rootLevel);
560                                }
561                                else
562                                {
563                                        strmQuery << EmptyRunIf << endl;
564                                }
565
566                                strm << "<p>Qualification: <br/>" << strmQuery.str() << "<p/>" << endl;
567
568
569                                strm << "<p>Max. Rows: " << fLimit.maxRetrieve << "<br/>" << endl;
570                                strm << "Num. Columns: " << fLimit.numColumns << "<p/>" << endl;                                               
571
572                                CTable colTab("tableColumnList", "TblObjectList");
573                                colTab.AddColumn(10,"Column Title");
574                                colTab.AddColumn(70,"Field");
575                                colTab.AddColumn(10,"Type");
576                                colTab.AddColumn(10,"Source");
577
578                                // get id of default vui
579                                CARVui defaultVUI(schema.GetInsideId(), schema.GetDefaultVUI());
580                                ARInternalId defaultVUIId = 0;
581                                if (defaultVUI.Exists())
582                                        defaultVUIId = defaultVUI.GetId();
583
584                                vector<ColumnWithOrder> columns; columns.reserve(fLimit.numColumns);
585                                unsigned int fieldCount = schema.GetFields()->GetCount();
586                                for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
587                                {
588                                        CARField columnField(schema.GetInsideId(), 0, fieldIndex);
589
590                                        if(columnField.GetDataType() == AR_DATA_TYPE_COLUMN)
591                                        {
592                                                const ARColumnLimitsStruct& colLimits = columnField.GetLimits().u.columnLimits;
593                                                if (colLimits.parent != this->field.GetInsideId()) { continue; } // this column doesn't belong to the current table
594
595                                                const ARDisplayInstanceList& dinstList = columnField.GetDisplayInstances();
596                                               
597                                                for (unsigned int dinstIndex = 0; dinstIndex < dinstList.numItems; ++dinstIndex)
598                                                {
599                                                        if (dinstList.dInstanceList[dinstIndex].vui == defaultVUIId)
600                                                        {
601                                                                const ARValueStruct* val = CARProplistHelper::Find(dinstList.dInstanceList[dinstIndex].props, AR_DPROP_COLUMN_ORDER);
602                                                                if (val != NULL && (val->dataType == AR_DATA_TYPE_INTEGER || val->dataType == AR_DATA_TYPE_ULONG))
603                                                                        columns.push_back(ColumnWithOrder(val->u.ulongVal, columnField));
604                                                                break;
605                                                        }
606                                                }
607
608                                        }
609                                }
610                                sort(columns.begin(), columns.end(), SortByColumnOrder(schema.GetInsideId()));
611
612                                /*unsigned int*/ fieldCount = schema.GetFields()->GetCount();
613                                for(unsigned int fieldIndex = 0; fieldIndex < columns.size(); ++fieldIndex)
614                                {
615                                        CARField columnField(columns[fieldIndex].field);
616
617                                        const ARColumnLimitsStruct& colLimits = columnField.GetLimits().u.columnLimits;
618                                        if (colLimits.parent != this->field.GetInsideId()) { continue; } // this column doesn't belong to the current table
619
620                                        CARField colSourceField;        // init to none-existing field
621
622                                        GetColumnSourceField(columnField, colSourceField, NULL);
623
624                                        // for the output we need the column label, that is stored as a property
625                                        // within the column. Each vui could have a different label for the column.
626                                        // Just use the defaultVUI.
627                                        const ARDisplayInstanceList& vuiList = columnField.GetDisplayInstances();
628                                        string label;
629
630                                        for (unsigned int vPos = 0; vPos < vuiList.numItems; ++vPos)
631                                        {
632                                                if (vuiList.dInstanceList[vPos].vui == defaultVUI.GetId())
633                                                {
634                                                        const ARPropList& props = vuiList.dInstanceList[vPos].props;
635                                                        ARValueStruct* val = CARProplistHelper::Find(props, AR_DPROP_LABEL);
636                                                        if (val != NULL && val->dataType == AR_DATA_TYPE_CHAR)
637                                                        {
638                                                                label = val->u.charVal;
639                                                        }
640                                                        // else
641                                                        //   keep it empty (but that shouldn't happen at all)
642                                                        break;
643                                                }
644                                        }
645
646                                        // now create the row
647                                        CTableRow tblRow;
648                                        tblRow.AddCell(label);
649                                        tblRow.AddCell(columnField.GetURL(rootLevel));
650                                        tblRow.AddCell((colSourceField.Exists() ? CAREnum::DataType(colSourceField.GetDataType()) : EnumDefault));
651                                        tblRow.AddCell(CAREnum::ColumnDataSourceType(colLimits.dataSource));
652                                        colTab.AddRow(tblRow);
653                                }
654                                strm << colTab << endl;
655                        }
656                        break;
657                case AR_DATA_TYPE_VIEW:
658                        {
659                                const ARViewLimits& fLimit = this->field.GetLimits().u.viewLimits;
660
661                                strm << "Max. Length: " << fLimit.maxLength << "<br/>" << endl;
662                        }
663                        break;                 
664                }
665        }
666        catch(exception& e)
667        {
668                cout << "EXCEPTION reading limits for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
669        }
670
671        return strm.str();
672}
673
674string CDocFieldDetails::DefaultValue()
675{
676        stringstream strm;
677        strm.str("");
678
679        try
680        {
681                switch(this->field.GetDefaultValue().dataType)
682                {
683                case AR_DATA_TYPE_KEYWORD:
684                        {
685                                strm << "$" << CARValue::ValueToString(this->field.GetDefaultValue()) << "$" << endl;
686                        }
687                        break;
688                case AR_DATA_TYPE_INTEGER:
689                case AR_DATA_TYPE_REAL:
690                case AR_DATA_TYPE_ENUM:
691                case AR_DATA_TYPE_TIME:
692                case AR_DATA_TYPE_DATE:
693                case AR_DATA_TYPE_TIME_OF_DAY:
694                        {
695                                strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
696                        }
697                        break;
698                case AR_DATA_TYPE_CHAR:
699                        {
700                                if(this->field.GetDefaultValue().u.charVal != NULL)
701                                {
702                                        strm << "\"" << pInside->TextFindFields(CARValue::ValueToString(this->field.GetDefaultValue()), "$", this->schema.GetInsideId(), rootLevel, true, NULL) << "\"" << endl;
703                                }
704                        }
705                        break;
706                case AR_DATA_TYPE_DIARY:
707                        {
708                                if(this->field.GetDefaultValue().u.diaryVal != NULL)
709                                {
710                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
711                                }
712                        }
713                        break; 
714                case AR_DATA_TYPE_DECIMAL:
715                        {
716                                if(this->field.GetDefaultValue().u.decimalVal != NULL)
717                                {
718                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
719                                }
720                        }
721                        break;
722                case AR_DATA_TYPE_CURRENCY:
723                        {
724                                if(this->field.GetDefaultValue().u.currencyVal->currencyCode != NULL)
725                                {
726                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
727                                }
728                        }
729                        break;
730                }
731        }
732        catch(exception& e)
733        {
734                cout << "EXCEPTION enumerating default value for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
735        }
736        return strm.str();
737}
738
739
740string CDocFieldDetails::Permisssions()
741{
742        stringstream strm;
743        strm.str("");
744
745        try
746        {
747                CTable tbl("fieldListAll", "TblObjectList");
748                tbl.AddColumn(5, "Permission");
749                tbl.AddColumn(10, "Description");
750                tbl.AddColumn(75, "Group Name");
751                tbl.AddColumn(10, "Group Id");
752
753                const ARPermissionList& perms = field.GetPermissions();
754                for(unsigned int i=0; i < perms.numItems; i++)
755                {
756                        string img;
757                        if(perms.permissionList[i].permissions == AR_PERMISSIONS_CHANGE)
758                                img = CWebUtil::ImageTag("edit.gif", rootLevel);
759                        else
760                                img = CWebUtil::ImageTag("visible.gif", rootLevel);
761
762                        CTableRow row("");
763                        row.AddCell( CTableCell(img));
764                        row.AddCell( CTableCell(CAREnum::FieldPermission(perms.permissionList[i].permissions)));
765                        row.AddCell( CTableCell(this->pInside->LinkToGroup(this->schema.GetAppRefName(), perms.permissionList[i].groupId, rootLevel)));
766                        row.AddCell( CTableCell(perms.permissionList[i].groupId));
767                        tbl.AddRow(row);
768                        row.ClearCells();
769                }
770
771                strm << tbl;
772        }
773        catch(exception& e)
774        {
775                cout << "EXCEPTION enumerating permissions for field: " << this->field.GetFieldId() << " in schema " << this->schema.GetName() << " error: " << e.what() << endl;
776        }       
777
778        return strm.str();
779}
780
781
782string CDocFieldDetails::DisplayProperties()
783{
784        stringstream strm;
785        strm.str("");
786
787        try
788        {
789                const ARDisplayInstanceList& dispList = field.GetDisplayInstances();
790                for(unsigned int i=0; i < dispList.numItems; i++)
791                {
792                        CTable tbl("displayPropList", "TblObjectList");
793                        tbl.AddColumn(20, "Description");
794                        tbl.AddColumn(80, "Values");
795
796                        for(unsigned int k=0; k < dispList.dInstanceList[i].props.numItems; k++)
797                        {
798                                const ARPropStruct &dProperty = dispList.dInstanceList[i].props.props[k];
799                               
800                                string value;
801
802                                //************** check for special properties here
803#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
804                                if ((dProperty.prop == AR_DPROP_PUSH_BUTTON_IMAGE || dProperty.prop == AR_DPROP_IMAGE) && dProperty.value.dataType == AR_DATA_TYPE_CHAR)
805                                {
806                                        CARImage img(dProperty.value.u.charVal);
807                                        if (img.Exists())
808                                        {
809                                                stringstream tmpDesc;
810                                                switch (dProperty.prop)
811                                                {
812                                                case AR_DPROP_PUSH_BUTTON_IMAGE:
813                                                case AR_DPROP_IMAGE:
814                                                        {
815                                                                CRefItem ref(field, REFM_BACKGROUND_IMAGE);
816                                                                img.AddReference(ref);
817                                                                break;
818                                                        }
819                                                }
820
821                                                value = img.GetURL(rootLevel);
822                                        }
823                                }
824#endif
825                                if (dProperty.prop == AR_DPROP_DISPLAY_PARENT && dProperty.value.u.ulongVal > 0)
826                                {
827                                        value = pInside->LinkToField(schema.GetInsideId(), dProperty.value.u.ulongVal, rootLevel);
828                                }
829                                //************** end of special properties
830
831                                if (value.empty())
832                                {
833                                        value = CARProplistHelper::GetValue(dProperty.prop, dProperty.value);
834                                }
835
836                                CTableRow row("");                     
837                                row.AddCell( CTableCell(CARProplistHelper::GetLabel(dProperty.prop)));
838                                row.AddCell( CTableCell(value));
839                                tbl.AddRow(row);                               
840                        }       
841
842                        stringstream viewTmpDesc;
843                        viewTmpDesc.str("");
844                        viewTmpDesc << "Display Properties in " << CWebUtil::Link("Schema",CPageParams(PAGE_DETAILS, &schema), "", rootLevel) << ", View: " << endl;
845                        viewTmpDesc << this->schema.LinkToVui(dispList.dInstanceList[i].vui, rootLevel);
846                        viewTmpDesc << " (Id: " << dispList.dInstanceList[i].vui << ", Label: " << this->schema.VuiGetLabel(dispList.dInstanceList[i].vui) << ")" << endl;
847
848
849                        tbl.description = viewTmpDesc.str();
850                        strm << tbl;
851                }       
852        }
853        catch(exception& e)
854        {
855                cout << "EXCEPTION enumerating display properties for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
856        }       
857
858        return strm.str();
859}
860
861string CDocFieldDetails::JoinFormReferences()
862{
863        stringstream strm;
864        strm.str("");
865
866        try
867        {
868                // TODO: each schema does the exact same scanning (see CDocSchemaDetails::JoinFormReferences), and each field
869                // scans for current schemas join-form references again. Maybe its possible to move this scanning to the
870                // scan-phase (so its executed only once per form) or we can temporarily store the result from the
871                // CDocSchemaDetails class and use it here again.
872                unsigned int schemaCount = this->pInside->schemaList.GetCount();
873                for (unsigned int schemaIndex = 0; schemaIndex < schemaCount; ++schemaIndex)
874                {                       
875                        CARSchema tmpSchema(schemaIndex);
876
877                        // skip this object in case it's overlaid (hidden)
878                        if (pInside->appConfig.bOverlaySupport && !IsVisibleObject(tmpSchema))
879                                continue;
880
881                        const ARCompoundSchema& comp = tmpSchema.GetCompound();
882                        if(comp.schemaType == AR_SCHEMA_JOIN)
883                        {
884                                //Primary Join Form referes to this schema
885                                if(strcmp(comp.u.join.memberA, this->schema.GetARName())==0)                                   
886                                {
887                                        unsigned int fieldCount = tmpSchema.GetFields()->GetCount();
888                                        for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
889                                        {
890                                                CARField tmpField(schemaIndex, 0, fieldIndex);
891                                                if(tmpField.GetMapping().u.join.realId == this->field.GetFieldId() && tmpField.GetMapping().u.join.schemaIndex == 0)
892                                                {
893                                                        strm << tmpField.GetURL(rootLevel) << " in Join-Form: ";
894                                                        strm << tmpSchema.GetURL(rootLevel) << "<br/>" << endl;
895                                                }
896                                        }
897                                }
898
899                                //Secondary Join Form refers to this schema
900                                if(strcmp(comp.u.join.memberB, this->schema.GetARName())==0)                                   
901                                {
902                                        unsigned int fieldCount = tmpSchema.GetFields()->GetCount();
903                                        for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
904                                        {
905                                                CARField tmpField(schemaIndex, 0, fieldIndex);
906                                                if(tmpField.GetMapping().u.join.realId == this->field.GetFieldId() && tmpField.GetMapping().u.join.schemaIndex == 1)
907                                                {
908                                                        strm << tmpField.GetURL(rootLevel) << " in Join-Form: ";
909                                                        strm << tmpSchema.GetURL(rootLevel) << "<br/>" << endl;
910                                                }
911                                        }
912                                }
913                        }
914                }
915
916                if(strm.str().size() == 0)
917                        strm << EmptyValue;
918        }
919        catch(exception& e)
920        {
921                cout << "EXCEPTION enumerating permissions for field: " << this->field.GetFieldId() << " in schema " << this->schema.GetName() << " error: " << e.what() << endl;
922        }       
923
924        return strm.str();
925}
926
927string CDocFieldDetails::FieldMapping()
928{
929        stringstream strm;
930        const ARFieldMappingStruct& map = this->field.GetMapping();
931        const ARCompoundSchema& compSchema = this->schema.GetCompound();
932
933        switch (map.fieldType)
934        {
935        case AR_FIELD_JOIN:
936                {
937                        if (this->field.GetFieldId() == 1)
938                        {
939                                strm << this->pInside->LinkToField(compSchema.u.join.memberA, 1, rootLevel) << "&nbsp;" << MenuSeparator << "&nbsp;" << this->pInside->LinkToSchema(compSchema.u.join.memberA, rootLevel) << "<br/>";
940                                strm << this->pInside->LinkToField(compSchema.u.join.memberB, 1, rootLevel) << "&nbsp;" << MenuSeparator << "&nbsp;" << this->pInside->LinkToSchema(compSchema.u.join.memberB, rootLevel);
941                        }
942                        else
943                        {
944                                string schemaName;
945
946                                strm << "Form Name: ";
947                                if (compSchema.schemaType == AR_SCHEMA_JOIN)
948                                {
949                                        if (map.u.join.schemaIndex == 0) // primary form
950                                                schemaName = compSchema.u.join.memberA;
951                                        else if (map.u.join.schemaIndex == 1) // secondary form
952                                                schemaName = compSchema.u.join.memberB;
953                                }
954
955                                CARSchema schema(schemaName);
956                                if (schema.Exists())
957                                        strm << schema.GetURL(this->rootLevel);
958                                else
959                                        strm << "<span class=\"fieldNotFound\">" << (schemaName.empty() ? EnumDefault : schemaName) << "</span>";
960                                strm << "<br/>";
961
962                                strm << "Field Name: ";
963                               
964                                CARField field(schema.GetInsideId(), map.u.join.realId);
965                                if (field.Exists())
966                                        strm << field.GetURL(this->rootLevel);
967                                else
968                                        strm << "<span class=\"fieldNotFound\">" << map.u.join.realId << "</span>";
969                        }
970                }
971                break;
972
973        case AR_FIELD_VIEW:
974                {
975                        strm << "Column: " << map.u.view.fieldName << "<br/>"; 
976                        strm << "Table: ";
977                       
978                        if (compSchema.schemaType == AR_SCHEMA_VIEW) 
979                                strm << compSchema.u.view.tableName;
980                        else
981                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
982                }
983                break;
984
985        case AR_FIELD_VENDOR:
986                {
987                        strm << "Column: " << map.u.vendor.fieldName << "<br/>";
988
989                        strm << "Vendor: ";
990                        if (compSchema.schemaType == AR_SCHEMA_VENDOR)
991                                strm << compSchema.u.vendor.vendorName;
992                        else
993                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
994                        strm << "<br/>";
995
996                        strm << "Table: ";
997                        if (compSchema.schemaType == AR_SCHEMA_VENDOR)
998                                strm << compSchema.u.vendor.tableName;
999                        else
1000                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
1001                }
1002                break;
1003        }
1004
1005        return strm.str();
1006}
1007
1008bool CDocFieldDetails::GetColumnSourceField(const CARField& col, CARField& source, std::string* colSourceSchemaName)
1009{
1010        if (col.GetLimits().dataType != AR_DATA_TYPE_COLUMN)
1011                throw AppException("invalid field type");
1012
1013        const ARColumnLimitsStruct& fLimit = col.GetLimits().u.columnLimits;
1014        CARSchema columnSourceForm; // initialize it to invalid form
1015        string columnSourceFormName;                           
1016
1017#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
1018        if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DISPLAY_FIELD || fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_CONTROL_FIELD)
1019#else
1020        if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DISPLAY_FIELD)
1021#endif
1022        {
1023                columnSourceForm = CARSchema(col.GetSchema().GetInsideId());
1024                columnSourceFormName = columnSourceForm.GetARName();
1025        }
1026        else if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DATA_FIELD)
1027        {
1028                CARField tableField(col.GetSchema().GetInsideId(), fLimit.parent);
1029                if (tableField.Exists() && tableField.GetDataType() == AR_DATA_TYPE_TABLE && tableField.GetLimits().dataType == AR_DATA_TYPE_TABLE)
1030                {
1031                        const ARFieldLimitStruct& limits = tableField.GetLimits();
1032                        columnSourceFormName = limits.u.tableLimits.schema;
1033
1034                        if (!columnSourceFormName.empty() && columnSourceFormName[0] == '$')
1035                                columnSourceFormName = limits.u.tableLimits.sampleSchema;
1036
1037                        if (columnSourceFormName.compare(AR_CURRENT_SCHEMA_TAG) == 0)
1038                                columnSourceFormName = col.GetSchema().GetARName();
1039                }
1040                columnSourceForm = CARSchema(columnSourceFormName);
1041        }
1042
1043        source = CARField(columnSourceForm.GetInsideId(), fLimit.dataField);
1044
1045        if (colSourceSchemaName)
1046        {
1047                (*colSourceSchemaName) = columnSourceFormName;
1048        }
1049
1050        return columnSourceForm.Exists();
1051}
1052
1053class SortRefItemByOrder
1054{
1055public:
1056        bool operator()(CRefItem& l, CRefItem& r) 
1057        {
1058                if (l.GetObjectOrder() == r.GetObjectOrder())
1059                {
1060                        return l.GetObjectName() < r.GetObjectName();
1061                }
1062                else if (l.GetObjectOrder() < r.GetObjectOrder())
1063                {
1064                        return true;
1065                }
1066                return false;
1067        }
1068
1069private:
1070        unsigned int GetOrderOf(CRefItem& ref)
1071        {
1072                switch (ref.GetObjectType())
1073                {
1074                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
1075                        {
1076                                CARActiveLink al(ref.GetObjectId());
1077                                return al.GetOrder();
1078                        }
1079                        break;
1080                default:
1081                        return 0;
1082                }
1083        }
1084};
1085
1086string CDocFieldDetails::WorkflowAttached()
1087{
1088        stringstream strm;
1089
1090        try
1091        {
1092                // temporary reference list
1093                CARField::ReferenceList attachedWF;
1094
1095                const CARField::ReferenceList& list = this->field.GetReferences();
1096                CARField::ReferenceList::const_iterator curIt = list.begin();
1097                CARField::ReferenceList::const_iterator endIt = list.end();
1098
1099                for (; curIt != endIt; ++curIt)
1100                {
1101                        int msgId = curIt->GetMessageId();
1102                        if (msgId == REFM_FOCUSFIELD || msgId == REFM_CONTROLFIELD)
1103                        {
1104                                attachedWF.push_back(*curIt);
1105                        }
1106                }
1107                attachedWF.sort(SortRefItemByOrder());
1108
1109                //Field references
1110                CTable tblRef("referenceList", "TblObjectList");
1111                tblRef.AddColumn(10, "Order");
1112                tblRef.AddColumn(45, "Server object");
1113                tblRef.AddColumn(5, "Enabled");
1114                tblRef.AddColumn(40, "Execute On");
1115
1116                curIt = attachedWF.begin();
1117                endIt = attachedWF.end();
1118
1119                for (; curIt != endIt; ++curIt)
1120                {
1121                        int enabled = curIt->GetObjectEnabled();
1122                        int order = curIt->GetObjectOrder();
1123                        string execution = curIt->GetObjectExecuteOn();
1124                        string cssEnabled;
1125
1126                        if (enabled == 0)
1127                                cssEnabled = "objStatusDisabled";
1128
1129                        CTableRow row("cssStdRow");
1130                        row.AddCell(CTableCell(order));
1131                        row.AddCell(pInside->LinkToObjByRefItem(*curIt, rootLevel));
1132                        row.AddCell(CTableCell(CAREnum::ObjectEnable(enabled), cssEnabled));
1133                        row.AddCell(execution);
1134                        tblRef.AddRow(row);
1135                }
1136
1137                if (tblRef.NumRows() > 0)
1138                        strm << tblRef;
1139        }
1140        catch (exception &e)
1141        {
1142                cout << "EXCEPTION enumerating attached workflow for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
1143        }
1144
1145        return strm.str();
1146}
Note: See TracBrowser for help on using the repository browser.