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

Revision 355, 36.1 KB checked in by jls17, 6 years ago (diff)
  • linking between field details and overview of schema-fields is working now
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 tableSchema;
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                                        tableSchema = fLimit.sampleSchema;
529
530                                        if (tableSchema.compare(AR_CURRENT_SCHEMA_TAG) == 0)
531                                                tableSchema = schema.GetARName();
532
533                                        strm << "$" << (fieldId < 0 ? CAREnum::Keyword(abs(fieldId)) : pInside->LinkToField(schema.GetInsideId(), fieldId, rootLevel) ) << "$ (Sample Form: " << pInside->LinkToSchema(tableSchema, 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                                        tableSchema = fLimit.schema;
544
545                                        if (tableSchema.compare(AR_CURRENT_SCHEMA_TAG) == 0)
546                                                tableSchema = schema.GetARName();
547
548                                        strm << this->pInside->LinkToSchema(tableSchema, 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
558                                        int pFormId = schema.GetInsideId();
559                                        int sFormId = this->pInside->SchemaGetInsideId(tableSchema);
560                                        arQual.CheckQuery(&fLimit.qualifier, refItem, 0, pFormId, sFormId, strmQuery, rootLevel);
561                                }
562                                else
563                                {
564                                        strmQuery << EmptyRunIf << endl;
565                                }
566
567                                strm << "<p>Qualification: <br/>" << strmQuery.str() << "<p/>" << endl;
568
569
570                                strm << "<p>Max. Rows: " << fLimit.maxRetrieve << "<br/>" << endl;
571                                strm << "Num. Columns: " << fLimit.numColumns << "<p/>" << endl;                                               
572
573                                CTable colTab("tableColumnList", "TblObjectList");
574                                colTab.AddColumn(10,"Column Title");
575                                colTab.AddColumn(70,"Field");
576                                colTab.AddColumn(10,"Type");
577                                colTab.AddColumn(10,"Source");
578
579                                // get id of default vui
580                                CARVui defaultVUI(schema.GetInsideId(), schema.GetDefaultVUI());
581                                ARInternalId defaultVUIId = 0;
582                                if (defaultVUI.Exists())
583                                        defaultVUIId = defaultVUI.GetId();
584
585                                vector<ColumnWithOrder> columns; columns.reserve(fLimit.numColumns);
586                                unsigned int fieldCount = schema.GetFields()->GetCount();
587                                for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
588                                {
589                                        CARField columnField(schema.GetInsideId(), 0, fieldIndex);
590
591                                        if(columnField.GetDataType() == AR_DATA_TYPE_COLUMN)
592                                        {
593                                                const ARColumnLimitsStruct& colLimits = columnField.GetLimits().u.columnLimits;
594                                                if (colLimits.parent != this->field.GetInsideId()) { continue; } // this column doesn't belong to the current table
595
596                                                const ARDisplayInstanceList& dinstList = columnField.GetDisplayInstances();
597                                               
598                                                for (unsigned int dinstIndex = 0; dinstIndex < dinstList.numItems; ++dinstIndex)
599                                                {
600                                                        if (dinstList.dInstanceList[dinstIndex].vui == defaultVUIId)
601                                                        {
602                                                                const ARValueStruct* val = CARProplistHelper::Find(dinstList.dInstanceList[dinstIndex].props, AR_DPROP_COLUMN_ORDER);
603                                                                if (val != NULL && (val->dataType == AR_DATA_TYPE_INTEGER || val->dataType == AR_DATA_TYPE_ULONG))
604                                                                        columns.push_back(ColumnWithOrder(val->u.ulongVal, columnField));
605                                                                break;
606                                                        }
607                                                }
608
609                                        }
610                                }
611                                sort(columns.begin(), columns.end(), SortByColumnOrder(schema.GetInsideId()));
612
613                                /*unsigned int*/ fieldCount = schema.GetFields()->GetCount();
614                                for(unsigned int fieldIndex = 0; fieldIndex < columns.size(); ++fieldIndex)
615                                {
616                                        CARField columnField(columns[fieldIndex].field);
617
618                                        const ARColumnLimitsStruct& colLimits = columnField.GetLimits().u.columnLimits;
619                                        if (colLimits.parent != this->field.GetInsideId()) { continue; } // this column doesn't belong to the current table
620
621                                        CARField colSourceField;        // init to none-existing field
622
623                                        GetColumnSourceField(columnField, colSourceField, NULL);
624
625                                        // for the output we need the column label, that is stored as a property
626                                        // within the column. Each vui could have a different label for the column.
627                                        // Just use the defaultVUI.
628                                        const ARDisplayInstanceList& vuiList = columnField.GetDisplayInstances();
629                                        string label;
630
631                                        for (unsigned int vPos = 0; vPos < vuiList.numItems; ++vPos)
632                                        {
633                                                if (vuiList.dInstanceList[vPos].vui == defaultVUI.GetId())
634                                                {
635                                                        const ARPropList& props = vuiList.dInstanceList[vPos].props;
636                                                        ARValueStruct* val = CARProplistHelper::Find(props, AR_DPROP_LABEL);
637                                                        if (val != NULL && val->dataType == AR_DATA_TYPE_CHAR)
638                                                        {
639                                                                label = val->u.charVal;
640                                                        }
641                                                        // else
642                                                        //   keep it empty (but that shouldn't happen at all)
643                                                        break;
644                                                }
645                                        }
646
647                                        // now create the row
648                                        CTableRow tblRow;
649                                        tblRow.AddCell(label);
650                                        tblRow.AddCell(columnField.GetURL(rootLevel));
651                                        tblRow.AddCell((colSourceField.Exists() ? CAREnum::DataType(colSourceField.GetDataType()) : EnumDefault));
652                                        tblRow.AddCell(CAREnum::ColumnDataSourceType(colLimits.dataSource));
653                                        colTab.AddRow(tblRow);
654                                }
655                                strm << colTab << endl;
656                        }
657                        break;
658                case AR_DATA_TYPE_VIEW:
659                        {
660                                const ARViewLimits& fLimit = this->field.GetLimits().u.viewLimits;
661
662                                strm << "Max. Length: " << fLimit.maxLength << "<br/>" << endl;
663                        }
664                        break;                 
665                }
666        }
667        catch(exception& e)
668        {
669                cout << "EXCEPTION reading limits for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
670        }
671
672        return strm.str();
673}
674
675string CDocFieldDetails::DefaultValue()
676{
677        stringstream strm;
678        strm.str("");
679
680        try
681        {
682                switch(this->field.GetDefaultValue().dataType)
683                {
684                case AR_DATA_TYPE_KEYWORD:
685                        {
686                                strm << "$" << CARValue::ValueToString(this->field.GetDefaultValue()) << "$" << endl;
687                        }
688                        break;
689                case AR_DATA_TYPE_INTEGER:
690                case AR_DATA_TYPE_REAL:
691                case AR_DATA_TYPE_ENUM:
692                case AR_DATA_TYPE_TIME:
693                case AR_DATA_TYPE_DATE:
694                case AR_DATA_TYPE_TIME_OF_DAY:
695                        {
696                                strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
697                        }
698                        break;
699                case AR_DATA_TYPE_CHAR:
700                        {
701                                if(this->field.GetDefaultValue().u.charVal != NULL)
702                                {
703                                        strm << "\"" << pInside->TextFindFields(CARValue::ValueToString(this->field.GetDefaultValue()), "$", this->schema.GetInsideId(), rootLevel, true, NULL) << "\"" << endl;
704                                }
705                        }
706                        break;
707                case AR_DATA_TYPE_DIARY:
708                        {
709                                if(this->field.GetDefaultValue().u.diaryVal != NULL)
710                                {
711                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
712                                }
713                        }
714                        break; 
715                case AR_DATA_TYPE_DECIMAL:
716                        {
717                                if(this->field.GetDefaultValue().u.decimalVal != NULL)
718                                {
719                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
720                                }
721                        }
722                        break;
723                case AR_DATA_TYPE_CURRENCY:
724                        {
725                                if(this->field.GetDefaultValue().u.currencyVal->currencyCode != NULL)
726                                {
727                                        strm << CARValue::ValueToString(this->field.GetDefaultValue()) << endl;
728                                }
729                        }
730                        break;
731                }
732        }
733        catch(exception& e)
734        {
735                cout << "EXCEPTION enumerating default value for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
736        }
737        return strm.str();
738}
739
740
741string CDocFieldDetails::Permisssions()
742{
743        stringstream strm;
744        strm.str("");
745
746        try
747        {
748                CTable tbl("fieldListAll", "TblObjectList");
749                tbl.AddColumn(5, "Permission");
750                tbl.AddColumn(10, "Description");
751                tbl.AddColumn(75, "Group Name");
752                tbl.AddColumn(10, "Group Id");
753
754                const ARPermissionList& perms = field.GetPermissions();
755                for(unsigned int i=0; i < perms.numItems; i++)
756                {
757                        string img;
758                        if(perms.permissionList[i].permissions == AR_PERMISSIONS_CHANGE)
759                                img = CWebUtil::ImageTag("edit.gif", rootLevel);
760                        else
761                                img = CWebUtil::ImageTag("visible.gif", rootLevel);
762
763                        CTableRow row("");
764                        row.AddCell( CTableCell(img));
765                        row.AddCell( CTableCell(CAREnum::FieldPermission(perms.permissionList[i].permissions)));
766                        row.AddCell( CTableCell(this->pInside->LinkToGroup(this->schema.GetAppRefName(), perms.permissionList[i].groupId, rootLevel)));
767                        row.AddCell( CTableCell(perms.permissionList[i].groupId));
768                        tbl.AddRow(row);
769                        row.ClearCells();
770                }
771
772                strm << tbl;
773        }
774        catch(exception& e)
775        {
776                cout << "EXCEPTION enumerating permissions for field: " << this->field.GetFieldId() << " in schema " << this->schema.GetName() << " error: " << e.what() << endl;
777        }       
778
779        return strm.str();
780}
781
782
783string CDocFieldDetails::DisplayProperties()
784{
785        stringstream strm;
786        strm.str("");
787
788        try
789        {
790                const ARDisplayInstanceList& dispList = field.GetDisplayInstances();
791                for(unsigned int i=0; i < dispList.numItems; i++)
792                {
793                        CTable tbl("displayPropList", "TblObjectList");
794                        tbl.AddColumn(20, "Description");
795                        tbl.AddColumn(80, "Values");
796
797                        for(unsigned int k=0; k < dispList.dInstanceList[i].props.numItems; k++)
798                        {
799                                const ARPropStruct &dProperty = dispList.dInstanceList[i].props.props[k];
800                               
801                                string value;
802
803                                //************** check for special properties here
804#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
805                                if ((dProperty.prop == AR_DPROP_PUSH_BUTTON_IMAGE || dProperty.prop == AR_DPROP_IMAGE) && dProperty.value.dataType == AR_DATA_TYPE_CHAR)
806                                {
807                                        CARImage img(dProperty.value.u.charVal);
808                                        if (img.Exists())
809                                        {
810                                                stringstream tmpDesc;
811                                                switch (dProperty.prop)
812                                                {
813                                                case AR_DPROP_PUSH_BUTTON_IMAGE:
814                                                case AR_DPROP_IMAGE:
815                                                        {
816                                                                CRefItem ref(field, REFM_BACKGROUND_IMAGE);
817                                                                img.AddReference(ref);
818                                                                break;
819                                                        }
820                                                }
821
822                                                value = img.GetURL(rootLevel);
823                                        }
824                                }
825#endif
826                                if (dProperty.prop == AR_DPROP_DISPLAY_PARENT && dProperty.value.u.ulongVal > 0)
827                                {
828                                        value = pInside->LinkToField(schema.GetInsideId(), dProperty.value.u.ulongVal, rootLevel);
829                                }
830                                //************** end of special properties
831
832                                if (value.empty())
833                                {
834                                        value = CARProplistHelper::GetValue(dProperty.prop, dProperty.value);
835                                }
836
837                                CTableRow row("");                     
838                                row.AddCell( CTableCell(CARProplistHelper::GetLabel(dProperty.prop)));
839                                row.AddCell( CTableCell(value));
840                                tbl.AddRow(row);                               
841                        }       
842
843                        stringstream viewTmpDesc;
844                        viewTmpDesc.str("");
845                        viewTmpDesc << "Display Properties in " << CWebUtil::Link("Schema",CPageParams(PAGE_DETAILS, &schema), "", rootLevel) << ", View: " << endl;
846                        viewTmpDesc << this->schema.LinkToVui(dispList.dInstanceList[i].vui, rootLevel);
847                        viewTmpDesc << " (Id: " << dispList.dInstanceList[i].vui << ", Label: " << this->schema.VuiGetLabel(dispList.dInstanceList[i].vui) << ")" << endl;
848
849
850                        tbl.description = viewTmpDesc.str();
851                        strm << tbl;
852                }       
853        }
854        catch(exception& e)
855        {
856                cout << "EXCEPTION enumerating display properties for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
857        }       
858
859        return strm.str();
860}
861
862string CDocFieldDetails::JoinFormReferences()
863{
864        stringstream strm;
865        strm.str("");
866
867        try
868        {
869                // TODO: each schema does the exact same scanning (see CDocSchemaDetails::JoinFormReferences), and each field
870                // scans for current schemas join-form references again. Maybe its possible to move this scanning to the
871                // scan-phase (so its executed only once per form) or we can temporarily store the result from the
872                // CDocSchemaDetails class and use it here again.
873                unsigned int schemaCount = this->pInside->schemaList.GetCount();
874                for (unsigned int schemaIndex = 0; schemaIndex < schemaCount; ++schemaIndex)
875                {                       
876                        CARSchema tmpSchema(schemaIndex);
877
878                        // skip this object in case it's overlaid (hidden)
879                        if (pInside->appConfig.bOverlaySupport && !IsVisibleObject(tmpSchema))
880                                continue;
881
882                        const ARCompoundSchema& comp = tmpSchema.GetCompound();
883                        if(comp.schemaType == AR_SCHEMA_JOIN)
884                        {
885                                //Primary Join Form referes to this schema
886                                if(strcmp(comp.u.join.memberA, this->schema.GetARName())==0)                                   
887                                {
888                                        unsigned int fieldCount = tmpSchema.GetFields()->GetCount();
889                                        for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
890                                        {
891                                                CARField tmpField(schemaIndex, 0, fieldIndex);
892                                                if(tmpField.GetMapping().u.join.realId == this->field.GetFieldId() && tmpField.GetMapping().u.join.schemaIndex == 0)
893                                                {
894                                                        strm << tmpField.GetURL(rootLevel) << " in Join-Form: ";
895                                                        strm << tmpSchema.GetURL(rootLevel) << "<br/>" << endl;
896                                                }
897                                        }
898                                }
899
900                                //Secondary Join Form refers to this schema
901                                if(strcmp(comp.u.join.memberB, this->schema.GetARName())==0)                                   
902                                {
903                                        unsigned int fieldCount = tmpSchema.GetFields()->GetCount();
904                                        for (unsigned int fieldIndex = 0; fieldIndex < fieldCount; ++fieldIndex)
905                                        {
906                                                CARField tmpField(schemaIndex, 0, fieldIndex);
907                                                if(tmpField.GetMapping().u.join.realId == this->field.GetFieldId() && tmpField.GetMapping().u.join.schemaIndex == 1)
908                                                {
909                                                        strm << tmpField.GetURL(rootLevel) << " in Join-Form: ";
910                                                        strm << tmpSchema.GetURL(rootLevel) << "<br/>" << endl;
911                                                }
912                                        }
913                                }
914                        }
915                }
916
917                if(strm.str().size() == 0)
918                        strm << EmptyValue;
919        }
920        catch(exception& e)
921        {
922                cout << "EXCEPTION enumerating permissions for field: " << this->field.GetFieldId() << " in schema " << this->schema.GetName() << " error: " << e.what() << endl;
923        }       
924
925        return strm.str();
926}
927
928string CDocFieldDetails::FieldMapping()
929{
930        stringstream strm;
931        const ARFieldMappingStruct& map = this->field.GetMapping();
932        const ARCompoundSchema& compSchema = this->schema.GetCompound();
933
934        switch (map.fieldType)
935        {
936        case AR_FIELD_JOIN:
937                {
938                        if (this->field.GetFieldId() == 1)
939                        {
940                                strm << this->pInside->LinkToField(compSchema.u.join.memberA, 1, rootLevel) << "&nbsp;" << MenuSeparator << "&nbsp;" << this->pInside->LinkToSchema(compSchema.u.join.memberA, rootLevel) << "<br/>";
941                                strm << this->pInside->LinkToField(compSchema.u.join.memberB, 1, rootLevel) << "&nbsp;" << MenuSeparator << "&nbsp;" << this->pInside->LinkToSchema(compSchema.u.join.memberB, rootLevel);
942                        }
943                        else
944                        {
945                                string schemaName;
946
947                                strm << "Form Name: ";
948                                if (compSchema.schemaType == AR_SCHEMA_JOIN)
949                                {
950                                        if (map.u.join.schemaIndex == 0) // primary form
951                                                schemaName = compSchema.u.join.memberA;
952                                        else if (map.u.join.schemaIndex == 1) // secondary form
953                                                schemaName = compSchema.u.join.memberB;
954                                }
955
956                                CARSchema schema(schemaName);
957                                if (schema.Exists())
958                                        strm << schema.GetURL(this->rootLevel);
959                                else
960                                        strm << "<span class=\"fieldNotFound\">" << (schemaName.empty() ? EnumDefault : schemaName) << "</span>";
961                                strm << "<br/>";
962
963                                strm << "Field Name: ";
964                               
965                                CARField field(schema.GetInsideId(), map.u.join.realId);
966                                if (field.Exists())
967                                        strm << field.GetURL(this->rootLevel);
968                                else
969                                        strm << "<span class=\"fieldNotFound\">" << map.u.join.realId << "</span>";
970                        }
971                }
972                break;
973
974        case AR_FIELD_VIEW:
975                {
976                        strm << "Column: " << map.u.view.fieldName << "<br/>"; 
977                        strm << "Table: ";
978                       
979                        if (compSchema.schemaType == AR_SCHEMA_VIEW) 
980                                strm << compSchema.u.view.tableName;
981                        else
982                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
983                }
984                break;
985
986        case AR_FIELD_VENDOR:
987                {
988                        strm << "Column: " << map.u.vendor.fieldName << "<br/>";
989
990                        strm << "Vendor: ";
991                        if (compSchema.schemaType == AR_SCHEMA_VENDOR)
992                                strm << compSchema.u.vendor.vendorName;
993                        else
994                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
995                        strm << "<br/>";
996
997                        strm << "Table: ";
998                        if (compSchema.schemaType == AR_SCHEMA_VENDOR)
999                                strm << compSchema.u.vendor.tableName;
1000                        else
1001                                strm << "<span class=\"fieldNotFound\">" << EnumDefault << "</span>";
1002                }
1003                break;
1004        }
1005
1006        return strm.str();
1007}
1008
1009bool CDocFieldDetails::GetColumnSourceField(const CARField& col, CARField& source, std::string* colSourceSchemaName)
1010{
1011        if (col.GetLimits().dataType != AR_DATA_TYPE_COLUMN)
1012                throw AppException("invalid field type");
1013
1014        const ARColumnLimitsStruct& fLimit = col.GetLimits().u.columnLimits;
1015        CARSchema columnSourceForm; // initialize it to invalid form
1016        string columnSourceFormName;                           
1017
1018#if AR_CURRENT_API_VERSION >= AR_API_VERSION_750
1019        if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DISPLAY_FIELD || fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_CONTROL_FIELD)
1020#else
1021        if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DISPLAY_FIELD)
1022#endif
1023        {
1024                columnSourceForm = CARSchema(col.GetSchema().GetInsideId());
1025                columnSourceFormName = columnSourceForm.GetARName();
1026        }
1027        else if (fLimit.dataSource == COLUMN_LIMIT_DATASOURCE_DATA_FIELD)
1028        {
1029                CARField tableField(col.GetSchema().GetInsideId(), fLimit.parent);
1030                if (tableField.Exists() && tableField.GetDataType() == AR_DATA_TYPE_TABLE && tableField.GetLimits().dataType == AR_DATA_TYPE_TABLE)
1031                {
1032                        const ARFieldLimitStruct& limits = tableField.GetLimits();
1033                        columnSourceFormName = limits.u.tableLimits.schema;
1034
1035                        if (!columnSourceFormName.empty() && columnSourceFormName[0] == '$')
1036                                columnSourceFormName = limits.u.tableLimits.sampleSchema;
1037
1038                        if (columnSourceFormName.compare(AR_CURRENT_SCHEMA_TAG) == 0)
1039                                columnSourceFormName = col.GetSchema().GetARName();
1040                }
1041                columnSourceForm = CARSchema(columnSourceFormName);
1042        }
1043
1044        source = CARField(columnSourceForm.GetInsideId(), fLimit.dataField);
1045
1046        if (colSourceSchemaName)
1047        {
1048                (*colSourceSchemaName) = columnSourceFormName;
1049        }
1050
1051        return columnSourceForm.Exists();
1052}
1053
1054class SortRefItemByOrder
1055{
1056public:
1057        bool operator()(CRefItem& l, CRefItem& r) 
1058        {
1059                if (l.GetObjectOrder() == r.GetObjectOrder())
1060                {
1061                        return l.GetObjectName() < r.GetObjectName();
1062                }
1063                else if (l.GetObjectOrder() < r.GetObjectOrder())
1064                {
1065                        return true;
1066                }
1067                return false;
1068        }
1069
1070private:
1071        unsigned int GetOrderOf(CRefItem& ref)
1072        {
1073                switch (ref.GetObjectType())
1074                {
1075                case AR_STRUCT_ITEM_XML_ACTIVE_LINK:
1076                        {
1077                                CARActiveLink al(ref.GetObjectId());
1078                                return al.GetOrder();
1079                        }
1080                        break;
1081                default:
1082                        return 0;
1083                }
1084        }
1085};
1086
1087string CDocFieldDetails::WorkflowAttached()
1088{
1089        stringstream strm;
1090
1091        try
1092        {
1093                // temporary reference list
1094                CARField::ReferenceList attachedWF;
1095
1096                const CARField::ReferenceList& list = this->field.GetReferences();
1097                CARField::ReferenceList::const_iterator curIt = list.begin();
1098                CARField::ReferenceList::const_iterator endIt = list.end();
1099
1100                for (; curIt != endIt; ++curIt)
1101                {
1102                        int msgId = curIt->GetMessageId();
1103                        if (msgId == REFM_FOCUSFIELD || msgId == REFM_CONTROLFIELD)
1104                        {
1105                                attachedWF.push_back(*curIt);
1106                        }
1107                }
1108                attachedWF.sort(SortRefItemByOrder());
1109
1110                //Field references
1111                CTable tblRef("referenceList", "TblObjectList");
1112                tblRef.AddColumn(10, "Order");
1113                tblRef.AddColumn(45, "Server object");
1114                tblRef.AddColumn(5, "Enabled");
1115                tblRef.AddColumn(40, "Execute On");
1116
1117                curIt = attachedWF.begin();
1118                endIt = attachedWF.end();
1119
1120                for (; curIt != endIt; ++curIt)
1121                {
1122                        int enabled = curIt->GetObjectEnabled();
1123                        int order = curIt->GetObjectOrder();
1124                        string execution = curIt->GetObjectExecuteOn();
1125                        string cssEnabled;
1126
1127                        if (enabled == 0)
1128                                cssEnabled = "objStatusDisabled";
1129
1130                        CTableRow row("cssStdRow");
1131                        row.AddCell(CTableCell(order));
1132                        row.AddCell(pInside->LinkToObjByRefItem(*curIt, rootLevel));
1133                        row.AddCell(CTableCell(CAREnum::ObjectEnable(enabled), cssEnabled));
1134                        row.AddCell(execution);
1135                        tblRef.AddRow(row);
1136                }
1137
1138                if (tblRef.NumRows() > 0)
1139                        strm << tblRef;
1140        }
1141        catch (exception &e)
1142        {
1143                cout << "EXCEPTION enumerating attached workflow for field: " << this->field.GetFieldId() <<" in schema " << this->schema.GetName() << " error: " << e.what() << endl;
1144        }
1145
1146        return strm.str();
1147}
Note: See TracBrowser for help on using the repository browser.